diff --git a/.gitignore b/.gitignore index 940794e..878de66 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# Project specific +FluentTerminal.App/Win32 + ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## diff --git a/FluentTerminal.App/App.xaml b/FluentTerminal.App/App.xaml new file mode 100644 index 0000000..061c2b0 --- /dev/null +++ b/FluentTerminal.App/App.xaml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/FluentTerminal.App/App.xaml.cs b/FluentTerminal.App/App.xaml.cs new file mode 100644 index 0000000..b52c062 --- /dev/null +++ b/FluentTerminal.App/App.xaml.cs @@ -0,0 +1,134 @@ +using FluentTerminal.App.Views; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Windows.ApplicationModel; +using Windows.ApplicationModel.Activation; +using Windows.ApplicationModel.AppService; +using Windows.ApplicationModel.Background; +using Windows.ApplicationModel.Core; +using Windows.UI.Core; +using Windows.UI.ViewManagement; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Navigation; + +namespace FluentTerminal.App +{ + sealed partial class App : Application + { + public App() + { + InitializeComponent(); + Instance = this; + } + + public static BackgroundTaskDeferral AppServiceDeferral = null; + public static AppServiceConnection Connection = null; + public static App Instance; + int? _settingsWindowId; + int idCreate = 0; + List idSaved = new List(); + + protected override async void OnLaunched(LaunchActivatedEventArgs e) + { + var launch = FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync().AsTask(); + var clearCache = WebView.ClearTemporaryWebDataAsync().AsTask(); + + await Task.WhenAll(launch, clearCache); + + Frame rootFrame = Window.Current.Content as Frame; + if (rootFrame == null) + { + rootFrame = new Frame(); + rootFrame.NavigationFailed += OnNavigationFailed; + Window.Current.Content = rootFrame; + } + + if (rootFrame.Content == null) + { + CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true; + rootFrame.Navigate(typeof(MainPage), e.Arguments); + idSaved.Add(ApplicationView.GetForCurrentView().Id); + } + else if (false) //todo: add option to create new windows on launch + { + await CreateNewWindow(typeof(MainPage), true); + } + Window.Current.Activate(); + } + + protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args) + { + // connection established from the fulltrust process + base.OnBackgroundActivated(args); + if (args.TaskInstance.TriggerDetails is AppServiceTriggerDetails details) + { + AppServiceDeferral = args.TaskInstance.GetDeferral(); + args.TaskInstance.Canceled += OnTaskCanceled; + Connection = details.AppServiceConnection; + Connection.RequestReceived += OnRequestReceived; + } + } + + private void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args) + { + if (args.Request.Message.ContainsKey("exit")) + { + App.Current.Exit(); + } + } + + private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) + { + if (AppServiceDeferral != null) + { + AppServiceDeferral.Complete(); + } + } + + public async Task CreateNewWindow(Type pageType, bool ExtendViewIntoTitleBar) + { + var create = CoreApplication.CreateNewView(); + await create.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = ExtendViewIntoTitleBar; + var frame = new Frame(); + frame.Navigate(pageType, null); + Window.Current.Content = frame; + Window.Current.Activate(); + + idCreate = ApplicationView.GetForCurrentView().Id; + }); + + for (int i = idSaved.Count - 1; i >= 0; i--) + if (await ApplicationViewSwitcher.TryShowAsStandaloneAsync( + idCreate, ViewSizePreference.Default, + idSaved[i], ViewSizePreference.Default) + ) break; + + idSaved.Add(idCreate); + return idCreate; + } + + public async Task ShowNew() + { + var id = await CreateNewWindow(typeof(MainPage), true); + bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(id); + } + + public async Task ShowSettings() + { + if (_settingsWindowId == null) + { + _settingsWindowId = await CreateNewWindow(typeof(Views.SettingsPage), false); + } + bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(_settingsWindowId.Value); + } + + void OnNavigationFailed(object sender, NavigationFailedEventArgs e) + { + throw new Exception("Failed to load Page " + e.SourcePageType.FullName); + } + } +} diff --git a/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-100.png b/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-100.png new file mode 100644 index 0000000..005c556 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-100.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-125.png b/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-125.png new file mode 100644 index 0000000..6e82690 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-125.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-150.png b/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-150.png new file mode 100644 index 0000000..36fd041 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-150.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-200.png b/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-200.png new file mode 100644 index 0000000..502c729 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-200.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-400.png b/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-400.png new file mode 100644 index 0000000..5cfc27a Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/LargeTile.scale-400.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-100.png b/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-100.png new file mode 100644 index 0000000..b9ae7b2 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-100.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-125.png b/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-125.png new file mode 100644 index 0000000..de32d18 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-125.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-150.png b/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-150.png new file mode 100644 index 0000000..a7ba7e0 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-150.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-200.png b/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-200.png new file mode 100644 index 0000000..947c1db Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-200.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-400.png b/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-400.png new file mode 100644 index 0000000..cd14362 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/SmallTile.scale-400.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-100.png b/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-100.png new file mode 100644 index 0000000..7c928b3 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-100.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-125.png b/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-125.png new file mode 100644 index 0000000..b7609d7 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-125.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-150.png b/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-150.png new file mode 100644 index 0000000..cf51216 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-150.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-200.png b/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-200.png new file mode 100644 index 0000000..0a15bf9 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-200.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-400.png b/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-400.png new file mode 100644 index 0000000..f854867 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/SplashScreen.scale-400.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-100.png b/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-100.png new file mode 100644 index 0000000..98af7ba Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-100.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-125.png b/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-125.png new file mode 100644 index 0000000..1d67187 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-125.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-150.png b/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-150.png new file mode 100644 index 0000000..23dcdb7 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-150.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-200.png b/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-200.png new file mode 100644 index 0000000..1b0d9a6 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-200.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-400.png b/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-400.png new file mode 100644 index 0000000..3d2f271 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square150x150Logo.scale-400.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-16.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-16.png new file mode 100644 index 0000000..1e25e8c Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-16.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-24.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-24.png new file mode 100644 index 0000000..1b9aa88 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-24.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-256.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-256.png new file mode 100644 index 0000000..3d60b54 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-256.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-32.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-32.png new file mode 100644 index 0000000..6771f2d Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-32.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-48.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-48.png new file mode 100644 index 0000000..811eaaf Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-48.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-100.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-100.png new file mode 100644 index 0000000..52e04e0 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-100.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-125.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-125.png new file mode 100644 index 0000000..7c68e13 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-125.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-150.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-150.png new file mode 100644 index 0000000..9f44a69 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-150.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-200.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-200.png new file mode 100644 index 0000000..7860992 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-200.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-400.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-400.png new file mode 100644 index 0000000..f453a83 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.scale-400.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-16.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-16.png new file mode 100644 index 0000000..104f3c9 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-16.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-24.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-24.png new file mode 100644 index 0000000..2939a36 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-24.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-256.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-256.png new file mode 100644 index 0000000..2fef7e8 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-256.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-32.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-32.png new file mode 100644 index 0000000..81abab6 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-32.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-48.png b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-48.png new file mode 100644 index 0000000..22e0e13 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Square44x44Logo.targetsize-48.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-100.png b/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-100.png new file mode 100644 index 0000000..b2de5ea Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-100.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-125.png b/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-125.png new file mode 100644 index 0000000..0c88789 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-125.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-150.png b/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-150.png new file mode 100644 index 0000000..5d518c1 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-150.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-200.png b/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-200.png new file mode 100644 index 0000000..dcc25df Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-200.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-400.png b/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-400.png new file mode 100644 index 0000000..9685d99 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/StoreLogo.scale-400.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-100.png b/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-100.png new file mode 100644 index 0000000..a7b3f7c Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-100.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-125.png b/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-125.png new file mode 100644 index 0000000..70c3d31 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-125.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-150.png b/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-150.png new file mode 100644 index 0000000..11f7081 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-150.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-200.png b/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000..7c928b3 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-200.png differ diff --git a/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-400.png b/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-400.png new file mode 100644 index 0000000..0a15bf9 Binary files /dev/null and b/FluentTerminal.App/Assets/AppIcons/Wide310x150Logo.scale-400.png differ diff --git a/FluentTerminal.App/Assets/LockScreenLogo.scale-200.png b/FluentTerminal.App/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 0000000..735f57a Binary files /dev/null and b/FluentTerminal.App/Assets/LockScreenLogo.scale-200.png differ diff --git a/FluentTerminal.App/Assets/SplashScreen.scale-200.png b/FluentTerminal.App/Assets/SplashScreen.scale-200.png new file mode 100644 index 0000000..023e7f1 Binary files /dev/null and b/FluentTerminal.App/Assets/SplashScreen.scale-200.png differ diff --git a/FluentTerminal.App/Assets/Square150x150Logo.scale-200.png b/FluentTerminal.App/Assets/Square150x150Logo.scale-200.png new file mode 100644 index 0000000..af49fec Binary files /dev/null and b/FluentTerminal.App/Assets/Square150x150Logo.scale-200.png differ diff --git a/FluentTerminal.App/Assets/Square44x44Logo.scale-200.png b/FluentTerminal.App/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 0000000..ce342a2 Binary files /dev/null and b/FluentTerminal.App/Assets/Square44x44Logo.scale-200.png differ diff --git a/FluentTerminal.App/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/FluentTerminal.App/Assets/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 0000000..f6c02ce Binary files /dev/null and b/FluentTerminal.App/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ diff --git a/FluentTerminal.App/Assets/StoreLogo.png b/FluentTerminal.App/Assets/StoreLogo.png new file mode 100644 index 0000000..7385b56 Binary files /dev/null and b/FluentTerminal.App/Assets/StoreLogo.png differ diff --git a/FluentTerminal.App/Assets/Wide310x150Logo.scale-200.png b/FluentTerminal.App/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000..288995b Binary files /dev/null and b/FluentTerminal.App/Assets/Wide310x150Logo.scale-200.png differ diff --git a/FluentTerminal.App/FluentTerminal.App.csproj b/FluentTerminal.App/FluentTerminal.App.csproj new file mode 100644 index 0000000..0749a6c --- /dev/null +++ b/FluentTerminal.App/FluentTerminal.App.csproj @@ -0,0 +1,264 @@ + + + + + Debug + x86 + {41020100-3414-4E0A-9A8E-92D3C4179DF8} + AppContainerExe + Properties + FluentTerminal.App + FluentTerminal.App + en-US + UAP + 10.0.16299.0 + 10.0.16299.0 + 14 + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + true + FluentTerminal.App_StoreKey.pfx + 8FA8EF727E767FAE5409DDD1694C1CEE054A2962 + True + Always + x86|x64 + + + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x86 + false + prompt + true + true + + + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + ARM + false + prompt + true + true + + + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x64 + false + prompt + true + + + bin\x64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x64 + false + prompt + true + true + + + PackageReference + + + + App.xaml + + + MainPage.xaml + + + + SettingsPage.xaml + + + TerminalPage.xaml + + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + PreserveNewest + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + + 6.0.6 + + + + + Windows Desktop Extensions for the UWP + + + + 14.0 + + + + mkdir "$(SolutionDir)\FluentTerminal.App\bin\$(PlatformName)\$(ConfigurationName)\AppX\Win32" 2> NULL +xcopy /y /s "$(SolutionDir)FluentTerminal.SystemTray\bin\$(PlatformName)\$(ConfigurationName)" "$(SolutionDir)\FluentTerminal.App\bin\$(PlatformName)\$(ConfigurationName)\AppX\Win32" + + + + \ No newline at end of file diff --git a/FluentTerminal.App/Package.appxmanifest b/FluentTerminal.App/Package.appxmanifest new file mode 100644 index 0000000..d49b8a5 --- /dev/null +++ b/FluentTerminal.App/Package.appxmanifest @@ -0,0 +1,41 @@ + + + + + + Fluent Terminal + FS Apps + Assets\AppIcons\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FluentTerminal.App/Properties/AssemblyInfo.cs b/FluentTerminal.App/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..259c9b0 --- /dev/null +++ b/FluentTerminal.App/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FluentTerminal.App")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FluentTerminal.App")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: ComVisible(false)] \ No newline at end of file diff --git a/FluentTerminal.App/Properties/Default.rd.xml b/FluentTerminal.App/Properties/Default.rd.xml new file mode 100644 index 0000000..cde328f --- /dev/null +++ b/FluentTerminal.App/Properties/Default.rd.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/FluentTerminal.App/Styles/Custom.xaml b/FluentTerminal.App/Styles/Custom.xaml new file mode 100644 index 0000000..44f41fb --- /dev/null +++ b/FluentTerminal.App/Styles/Custom.xaml @@ -0,0 +1,71 @@ + + + + + + + + + + diff --git a/FluentTerminal.App/Views/MainPage.xaml b/FluentTerminal.App/Views/MainPage.xaml new file mode 100644 index 0000000..776f3b6 --- /dev/null +++ b/FluentTerminal.App/Views/MainPage.xaml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FluentTerminal.App/Views/MainPage.xaml.cs b/FluentTerminal.App/Views/MainPage.xaml.cs new file mode 100644 index 0000000..51e4651 --- /dev/null +++ b/FluentTerminal.App/Views/MainPage.xaml.cs @@ -0,0 +1,97 @@ +using System.ComponentModel; +using Windows.ApplicationModel.Core; +using Windows.UI; +using Windows.UI.Core; +using Windows.UI.ViewManagement; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace FluentTerminal.App.Views +{ + public sealed partial class MainPage : Page, INotifyPropertyChanged + { + private readonly CoreApplicationViewTitleBar coreTitleBar = CoreApplication.GetCurrentView().TitleBar; + + public event PropertyChangedEventHandler PropertyChanged; + + public double CoreTitleBarHeight => coreTitleBar.Height; + + public Thickness CoreTitleBarPadding + { + get + { + if (FlowDirection == FlowDirection.LeftToRight) + { + return new Thickness { Left = coreTitleBar.SystemOverlayLeftInset, Right = coreTitleBar.SystemOverlayRightInset }; + } + else + { + return new Thickness { Left = coreTitleBar.SystemOverlayRightInset, Right = coreTitleBar.SystemOverlayLeftInset }; + } + } + } + + public MainPage() + { + InitializeComponent(); + Root.DataContext = this; + SetTitleBarColors(); + Window.Current.SetTitleBar(TitleBar); + Loaded += OnLoaded; + Unloaded += OnUnloaded; + Window.Current.Activated += OnWindowActivated; + } + + private async void OnWindowActivated(object sender, WindowActivatedEventArgs e) + { + if (e.WindowActivationState != CoreWindowActivationState.Deactivated && RootFrame.Content is TerminalPage terminal) + { + await terminal.FocusWebView(); + } + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + coreTitleBar.LayoutMetricsChanged -= OnLayoutMetricsChanged; + } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + coreTitleBar.LayoutMetricsChanged += OnLayoutMetricsChanged; + UpdateLayoutMetrics(); + RootFrame.Navigate(typeof(TerminalPage)); + } + + private void OnLayoutMetricsChanged(CoreApplicationViewTitleBar sender, object e) + { + UpdateLayoutMetrics(); + } + + private void SetTitleBarColors() + { + var titleBar = ApplicationView.GetForCurrentView().TitleBar; + titleBar.ButtonBackgroundColor = Colors.Transparent; + titleBar.ButtonInactiveBackgroundColor = Colors.Transparent; + titleBar.ButtonForegroundColor = Colors.White; + titleBar.ButtonInactiveForegroundColor = Colors.White; + titleBar.ButtonPressedForegroundColor = Colors.White; + titleBar.ButtonHoverForegroundColor = Colors.White; + titleBar.ButtonHoverBackgroundColor = Color.FromArgb(24, 255, 255, 255); + titleBar.ButtonPressedBackgroundColor = Color.FromArgb(48, 255, 255, 255); + } + + private void UpdateLayoutMetrics() + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(nameof(CoreTitleBarHeight))); + PropertyChanged(this, new PropertyChangedEventArgs(nameof(CoreTitleBarPadding))); + } + } + + private async void OnSettingsButtonClick(object sender, RoutedEventArgs e) + { + await App.Instance.ShowSettings(); + } + } +} diff --git a/FluentTerminal.App/Views/SettingsPage.xaml b/FluentTerminal.App/Views/SettingsPage.xaml new file mode 100644 index 0000000..69ec4c4 --- /dev/null +++ b/FluentTerminal.App/Views/SettingsPage.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/FluentTerminal.App/Views/SettingsPage.xaml.cs b/FluentTerminal.App/Views/SettingsPage.xaml.cs new file mode 100644 index 0000000..758e541 --- /dev/null +++ b/FluentTerminal.App/Views/SettingsPage.xaml.cs @@ -0,0 +1,12 @@ +using Windows.UI.Xaml.Controls; + +namespace FluentTerminal.App.Views +{ + public sealed partial class SettingsPage : Page + { + public SettingsPage() + { + this.InitializeComponent(); + } + } +} diff --git a/FluentTerminal.App/Views/TerminalPage.xaml b/FluentTerminal.App/Views/TerminalPage.xaml new file mode 100644 index 0000000..661876d --- /dev/null +++ b/FluentTerminal.App/Views/TerminalPage.xaml @@ -0,0 +1,9 @@ + + + diff --git a/FluentTerminal.App/Views/TerminalPage.xaml.cs b/FluentTerminal.App/Views/TerminalPage.xaml.cs new file mode 100644 index 0000000..7743cec --- /dev/null +++ b/FluentTerminal.App/Views/TerminalPage.xaml.cs @@ -0,0 +1,65 @@ +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using Windows.UI; +using Windows.UI.Core.Preview; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace FluentTerminal.App.Views +{ + public sealed partial class TerminalPage : Page + { + private WebView _webView; + + public TerminalPage() + { + InitializeComponent(); + Loaded += OnLoaded; + SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += OnCloseRequested; + } + + public async Task FocusWebView() + { + if (_webView != null) + { + _webView.Focus(FocusState.Programmatic); + await ExecuteScriptAsync("document.focus();"); + } + } + + private void OnCloseRequested(object sender, SystemNavigationCloseRequestedPreviewEventArgs e) + { + _webView.Navigate(new Uri("about:blank")); + _webView = null; + } + + public Task ExecuteScriptAsync(string script) + { + try + { + return _webView.InvokeScriptAsync("eval", new[] + { + "try {" + script + "} catch(error) {}" + }).AsTask(); + } + catch (Exception e) + { + Debug.WriteLine($"Exception while running:\n \"{script}\"\n\n {e}"); + } + return Task.FromResult(string.Empty); + } + + private async void OnLoaded(object sender, RoutedEventArgs e) + { + _webView = new WebView(WebViewExecutionMode.SeparateThread) + { + DefaultBackgroundColor = Colors.Transparent + }; + WebViewContainer.Children.Add(_webView); + + _webView.Navigate(new Uri("http://localhost:9000/Client/index.html")); + _webView.Focus(FocusState.Programmatic); + } + } +} diff --git a/FluentTerminal.Client/.gitignore b/FluentTerminal.Client/.gitignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/FluentTerminal.Client/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/FluentTerminal.Client/dist/bundle.js b/FluentTerminal.Client/dist/bundle.js new file mode 100644 index 0000000..04f280a --- /dev/null +++ b/FluentTerminal.Client/dist/bundle.js @@ -0,0 +1,6618 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__xterm_js_build_addons_attach_attach__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__xterm_js_build_addons_attach_attach___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__xterm_js_build_addons_attach_attach__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__xterm_js_build_addons_fit_fit__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__xterm_js_build_addons_fit_fit___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2__xterm_js_build_addons_fit_fit__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__xterm_js_build_addons_winptyCompat_winptyCompat__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__xterm_js_build_addons_winptyCompat_winptyCompat___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3__xterm_js_build_addons_winptyCompat_winptyCompat__); + + + + + +__WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm__["applyAddon"](__WEBPACK_IMPORTED_MODULE_1__xterm_js_build_addons_attach_attach__); +__WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm__["applyAddon"](__WEBPACK_IMPORTED_MODULE_2__xterm_js_build_addons_fit_fit__); +__WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm__["applyAddon"](__WEBPACK_IMPORTED_MODULE_3__xterm_js_build_addons_winptyCompat_winptyCompat__); + +var term, protocol, socketURL, socket; +var terminalContainer = document.getElementById('terminal-container'); + +createTerminal(); + +function createTerminal() { + while (terminalContainer.children.length) { + terminalContainer.removeChild(terminalContainer.children[0]); + } + term = new __WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm__({ + cursorBlink: true, + fontFamily: 'consolas', + fontSize: 13, + allowTransparency: true, + theme: { + background: "transparent" + } + }); + window.term = term; // Expose `term` to window for debugging purposes + term.on('resize', function (size) { + if (!socketURL) { + return; + } + var cols = size.cols, + rows = size.rows, + url = 'http://localhost:9000/terminals/' + pid + '/size?cols=' + cols + '&rows=' + rows; + fetch(url, {method: 'POST'}); + }); + protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://'; + + term.open(terminalContainer); + term.winptyCompatInit(); + term.fit(); + term.focus(); + + fetch('http://localhost:9000/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then(function (res) { + console.log("got response"); + res.text().then(function (url) { + socketURL = JSON.parse(url); + socket = new WebSocket(socketURL); + socket.onopen = runRealTerminal; + }); + }); +} + +function runRealTerminal() { + term.attach(socket); + term._initialized = true; +} + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + +var require;var require;(function(f){if(true){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Terminal = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return require(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o this._terminal.rows; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Buffer.prototype, "isCursorInViewport", { + get: function () { + var absoluteY = this.ybase + this.y; + var relativeY = absoluteY - this.ydisp; + return (relativeY >= 0 && relativeY < this._terminal.rows); + }, + enumerable: true, + configurable: true + }); + Buffer.prototype._getCorrectBufferLength = function (rows) { + if (!this._hasScrollback) { + return rows; + } + var correctBufferLength = rows + this._terminal.options.scrollback; + return correctBufferLength > exports.MAX_BUFFER_SIZE ? exports.MAX_BUFFER_SIZE : correctBufferLength; + }; + Buffer.prototype.fillViewportRows = function () { + if (this._lines.length === 0) { + var i = this._terminal.rows; + while (i--) { + this.lines.push(this._terminal.blankLine()); + } + } + }; + Buffer.prototype.clear = function () { + this.ydisp = 0; + this.ybase = 0; + this.y = 0; + this.x = 0; + this._lines = new CircularList_1.CircularList(this._getCorrectBufferLength(this._terminal.rows)); + this.scrollTop = 0; + this.scrollBottom = this._terminal.rows - 1; + this.setupTabStops(); + }; + Buffer.prototype.resize = function (newCols, newRows) { + var newMaxLength = this._getCorrectBufferLength(newRows); + if (newMaxLength > this._lines.maxLength) { + this._lines.maxLength = newMaxLength; + } + if (this._lines.length > 0) { + if (this._terminal.cols < newCols) { + var ch = [this._terminal.defAttr, ' ', 1, 32]; + for (var i = 0; i < this._lines.length; i++) { + if (this._lines.get(i) === undefined) { + this._lines.set(i, this._terminal.blankLine(undefined, undefined, newCols)); + } + while (this._lines.get(i).length < newCols) { + this._lines.get(i).push(ch); + } + } + } + var addToY = 0; + if (this._terminal.rows < newRows) { + for (var y = this._terminal.rows; y < newRows; y++) { + if (this._lines.length < newRows + this.ybase) { + if (this.ybase > 0 && this._lines.length <= this.ybase + this.y + addToY + 1) { + this.ybase--; + addToY++; + if (this.ydisp > 0) { + this.ydisp--; + } + } + else { + this._lines.push(this._terminal.blankLine(undefined, undefined, newCols)); + } + } + } + } + else { + for (var y = this._terminal.rows; y > newRows; y--) { + if (this._lines.length > newRows + this.ybase) { + if (this._lines.length > this.ybase + this.y + 1) { + this._lines.pop(); + } + else { + this.ybase++; + this.ydisp++; + } + } + } + } + if (newMaxLength < this._lines.maxLength) { + var amountToTrim = this._lines.length - newMaxLength; + if (amountToTrim > 0) { + this._lines.trimStart(amountToTrim); + this.ybase = Math.max(this.ybase - amountToTrim, 0); + this.ydisp = Math.max(this.ydisp - amountToTrim, 0); + } + this._lines.maxLength = newMaxLength; + } + if (this.y >= newRows) { + this.y = newRows - 1; + } + if (addToY) { + this.y += addToY; + } + if (this.x >= newCols) { + this.x = newCols - 1; + } + this.scrollTop = 0; + } + this.scrollBottom = newRows - 1; + }; + Buffer.prototype.translateBufferLineToString = function (lineIndex, trimRight, startCol, endCol) { + if (startCol === void 0) { startCol = 0; } + if (endCol === void 0) { endCol = null; } + var lineString = ''; + var line = this.lines.get(lineIndex); + if (!line) { + return ''; + } + var startIndex = startCol; + endCol = endCol || line.length; + var endIndex = endCol; + for (var i = 0; i < line.length; i++) { + var char = line[i]; + lineString += char[exports.CHAR_DATA_CHAR_INDEX]; + if (char[exports.CHAR_DATA_WIDTH_INDEX] === 0) { + if (startCol >= i) { + startIndex--; + } + if (endCol >= i) { + endIndex--; + } + } + else { + if (char[exports.CHAR_DATA_CHAR_INDEX].length > 1) { + if (startCol > i) { + startIndex += char[exports.CHAR_DATA_CHAR_INDEX].length - 1; + } + if (endCol > i) { + endIndex += char[exports.CHAR_DATA_CHAR_INDEX].length - 1; + } + } + } + } + if (trimRight) { + var rightWhitespaceIndex = lineString.search(/\s+$/); + if (rightWhitespaceIndex !== -1) { + endIndex = Math.min(endIndex, rightWhitespaceIndex); + } + if (endIndex <= startIndex) { + return ''; + } + } + return lineString.substring(startIndex, endIndex); + }; + Buffer.prototype.setupTabStops = function (i) { + if (i != null) { + if (!this.tabs[i]) { + i = this.prevStop(i); + } + } + else { + this.tabs = {}; + i = 0; + } + for (; i < this._terminal.cols; i += this._terminal.options.tabStopWidth) { + this.tabs[i] = true; + } + }; + Buffer.prototype.prevStop = function (x) { + if (x == null) { + x = this.x; + } + while (!this.tabs[--x] && x > 0) + ; + return x >= this._terminal.cols ? this._terminal.cols - 1 : x < 0 ? 0 : x; + }; + Buffer.prototype.nextStop = function (x) { + if (x == null) { + x = this.x; + } + while (!this.tabs[++x] && x < this._terminal.cols) + ; + return x >= this._terminal.cols ? this._terminal.cols - 1 : x < 0 ? 0 : x; + }; + return Buffer; +}()); +exports.Buffer = Buffer; + + + +},{"./utils/CircularList":30}],2:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Buffer_1 = require("./Buffer"); +var EventEmitter_1 = require("./EventEmitter"); +var BufferSet = (function (_super) { + __extends(BufferSet, _super); + function BufferSet(_terminal) { + var _this = _super.call(this) || this; + _this._terminal = _terminal; + _this._normal = new Buffer_1.Buffer(_this._terminal, true); + _this._normal.fillViewportRows(); + _this._alt = new Buffer_1.Buffer(_this._terminal, false); + _this._activeBuffer = _this._normal; + _this.setupTabStops(); + return _this; + } + Object.defineProperty(BufferSet.prototype, "alt", { + get: function () { + return this._alt; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(BufferSet.prototype, "active", { + get: function () { + return this._activeBuffer; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(BufferSet.prototype, "normal", { + get: function () { + return this._normal; + }, + enumerable: true, + configurable: true + }); + BufferSet.prototype.activateNormalBuffer = function () { + this._alt.clear(); + this._activeBuffer = this._normal; + this.emit('activate', this._normal); + }; + BufferSet.prototype.activateAltBuffer = function () { + this._alt.fillViewportRows(); + this._activeBuffer = this._alt; + this.emit('activate', this._alt); + }; + BufferSet.prototype.resize = function (newCols, newRows) { + this._normal.resize(newCols, newRows); + this._alt.resize(newCols, newRows); + }; + BufferSet.prototype.setupTabStops = function (i) { + this._normal.setupTabStops(i); + this._alt.setupTabStops(i); + }; + return BufferSet; +}(EventEmitter_1.EventEmitter)); +exports.BufferSet = BufferSet; + + + +},{"./Buffer":1,"./EventEmitter":7}],3:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.wcwidth = (function (opts) { + var COMBINING_BMP = [ + [0x0300, 0x036F], [0x0483, 0x0486], [0x0488, 0x0489], + [0x0591, 0x05BD], [0x05BF, 0x05BF], [0x05C1, 0x05C2], + [0x05C4, 0x05C5], [0x05C7, 0x05C7], [0x0600, 0x0603], + [0x0610, 0x0615], [0x064B, 0x065E], [0x0670, 0x0670], + [0x06D6, 0x06E4], [0x06E7, 0x06E8], [0x06EA, 0x06ED], + [0x070F, 0x070F], [0x0711, 0x0711], [0x0730, 0x074A], + [0x07A6, 0x07B0], [0x07EB, 0x07F3], [0x0901, 0x0902], + [0x093C, 0x093C], [0x0941, 0x0948], [0x094D, 0x094D], + [0x0951, 0x0954], [0x0962, 0x0963], [0x0981, 0x0981], + [0x09BC, 0x09BC], [0x09C1, 0x09C4], [0x09CD, 0x09CD], + [0x09E2, 0x09E3], [0x0A01, 0x0A02], [0x0A3C, 0x0A3C], + [0x0A41, 0x0A42], [0x0A47, 0x0A48], [0x0A4B, 0x0A4D], + [0x0A70, 0x0A71], [0x0A81, 0x0A82], [0x0ABC, 0x0ABC], + [0x0AC1, 0x0AC5], [0x0AC7, 0x0AC8], [0x0ACD, 0x0ACD], + [0x0AE2, 0x0AE3], [0x0B01, 0x0B01], [0x0B3C, 0x0B3C], + [0x0B3F, 0x0B3F], [0x0B41, 0x0B43], [0x0B4D, 0x0B4D], + [0x0B56, 0x0B56], [0x0B82, 0x0B82], [0x0BC0, 0x0BC0], + [0x0BCD, 0x0BCD], [0x0C3E, 0x0C40], [0x0C46, 0x0C48], + [0x0C4A, 0x0C4D], [0x0C55, 0x0C56], [0x0CBC, 0x0CBC], + [0x0CBF, 0x0CBF], [0x0CC6, 0x0CC6], [0x0CCC, 0x0CCD], + [0x0CE2, 0x0CE3], [0x0D41, 0x0D43], [0x0D4D, 0x0D4D], + [0x0DCA, 0x0DCA], [0x0DD2, 0x0DD4], [0x0DD6, 0x0DD6], + [0x0E31, 0x0E31], [0x0E34, 0x0E3A], [0x0E47, 0x0E4E], + [0x0EB1, 0x0EB1], [0x0EB4, 0x0EB9], [0x0EBB, 0x0EBC], + [0x0EC8, 0x0ECD], [0x0F18, 0x0F19], [0x0F35, 0x0F35], + [0x0F37, 0x0F37], [0x0F39, 0x0F39], [0x0F71, 0x0F7E], + [0x0F80, 0x0F84], [0x0F86, 0x0F87], [0x0F90, 0x0F97], + [0x0F99, 0x0FBC], [0x0FC6, 0x0FC6], [0x102D, 0x1030], + [0x1032, 0x1032], [0x1036, 0x1037], [0x1039, 0x1039], + [0x1058, 0x1059], [0x1160, 0x11FF], [0x135F, 0x135F], + [0x1712, 0x1714], [0x1732, 0x1734], [0x1752, 0x1753], + [0x1772, 0x1773], [0x17B4, 0x17B5], [0x17B7, 0x17BD], + [0x17C6, 0x17C6], [0x17C9, 0x17D3], [0x17DD, 0x17DD], + [0x180B, 0x180D], [0x18A9, 0x18A9], [0x1920, 0x1922], + [0x1927, 0x1928], [0x1932, 0x1932], [0x1939, 0x193B], + [0x1A17, 0x1A18], [0x1B00, 0x1B03], [0x1B34, 0x1B34], + [0x1B36, 0x1B3A], [0x1B3C, 0x1B3C], [0x1B42, 0x1B42], + [0x1B6B, 0x1B73], [0x1DC0, 0x1DCA], [0x1DFE, 0x1DFF], + [0x200B, 0x200F], [0x202A, 0x202E], [0x2060, 0x2063], + [0x206A, 0x206F], [0x20D0, 0x20EF], [0x302A, 0x302F], + [0x3099, 0x309A], [0xA806, 0xA806], [0xA80B, 0xA80B], + [0xA825, 0xA826], [0xFB1E, 0xFB1E], [0xFE00, 0xFE0F], + [0xFE20, 0xFE23], [0xFEFF, 0xFEFF], [0xFFF9, 0xFFFB], + ]; + var COMBINING_HIGH = [ + [0x10A01, 0x10A03], [0x10A05, 0x10A06], [0x10A0C, 0x10A0F], + [0x10A38, 0x10A3A], [0x10A3F, 0x10A3F], [0x1D167, 0x1D169], + [0x1D173, 0x1D182], [0x1D185, 0x1D18B], [0x1D1AA, 0x1D1AD], + [0x1D242, 0x1D244], [0xE0001, 0xE0001], [0xE0020, 0xE007F], + [0xE0100, 0xE01EF] + ]; + function bisearch(ucs, data) { + var min = 0; + var max = data.length - 1; + var mid; + if (ucs < data[0][0] || ucs > data[max][1]) + return false; + while (max >= min) { + mid = (min + max) >> 1; + if (ucs > data[mid][1]) + min = mid + 1; + else if (ucs < data[mid][0]) + max = mid - 1; + else + return true; + } + return false; + } + function wcwidthBMP(ucs) { + if (ucs === 0) + return opts.nul; + if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) + return opts.control; + if (bisearch(ucs, COMBINING_BMP)) + return 0; + if (isWideBMP(ucs)) { + return 2; + } + return 1; + } + function isWideBMP(ucs) { + return (ucs >= 0x1100 && (ucs <= 0x115f || + ucs === 0x2329 || + ucs === 0x232a || + (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs !== 0x303f) || + (ucs >= 0xac00 && ucs <= 0xd7a3) || + (ucs >= 0xf900 && ucs <= 0xfaff) || + (ucs >= 0xfe10 && ucs <= 0xfe19) || + (ucs >= 0xfe30 && ucs <= 0xfe6f) || + (ucs >= 0xff00 && ucs <= 0xff60) || + (ucs >= 0xffe0 && ucs <= 0xffe6))); + } + function wcwidthHigh(ucs) { + if (bisearch(ucs, COMBINING_HIGH)) + return 0; + if ((ucs >= 0x20000 && ucs <= 0x2fffd) || (ucs >= 0x30000 && ucs <= 0x3fffd)) { + return 2; + } + return 1; + } + var control = opts.control | 0; + var table = null; + function init_table() { + var CODEPOINTS = 65536; + var BITWIDTH = 2; + var ITEMSIZE = 32; + var CONTAINERSIZE = CODEPOINTS * BITWIDTH / ITEMSIZE; + var CODEPOINTS_PER_ITEM = ITEMSIZE / BITWIDTH; + table = (typeof Uint32Array === 'undefined') + ? new Array(CONTAINERSIZE) + : new Uint32Array(CONTAINERSIZE); + for (var i = 0; i < CONTAINERSIZE; ++i) { + var num = 0; + var pos = CODEPOINTS_PER_ITEM; + while (pos--) + num = (num << 2) | wcwidthBMP(CODEPOINTS_PER_ITEM * i + pos); + table[i] = num; + } + return table; + } + return function (num) { + num = num | 0; + if (num < 32) + return control | 0; + if (num < 127) + return 1; + var t = table || init_table(); + if (num < 65536) + return t[num >> 4] >> ((num & 15) << 1) & 3; + return wcwidthHigh(num); + }; +})({ nul: 0, control: 0 }); + + + +},{}],4:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CHARSETS = {}; +exports.DEFAULT_CHARSET = exports.CHARSETS['B']; +exports.CHARSETS['0'] = { + '`': '\u25c6', + 'a': '\u2592', + 'b': '\u0009', + 'c': '\u000c', + 'd': '\u000d', + 'e': '\u000a', + 'f': '\u00b0', + 'g': '\u00b1', + 'h': '\u2424', + 'i': '\u000b', + 'j': '\u2518', + 'k': '\u2510', + 'l': '\u250c', + 'm': '\u2514', + 'n': '\u253c', + 'o': '\u23ba', + 'p': '\u23bb', + 'q': '\u2500', + 'r': '\u23bc', + 's': '\u23bd', + 't': '\u251c', + 'u': '\u2524', + 'v': '\u2534', + 'w': '\u252c', + 'x': '\u2502', + 'y': '\u2264', + 'z': '\u2265', + '{': '\u03c0', + '|': '\u2260', + '}': '\u00a3', + '~': '\u00b7' +}; +exports.CHARSETS['A'] = { + '#': '£' +}; +exports.CHARSETS['B'] = null; +exports.CHARSETS['4'] = { + '#': '£', + '@': '¾', + '[': 'ij', + '\\': '½', + ']': '|', + '{': '¨', + '|': 'f', + '}': '¼', + '~': '´' +}; +exports.CHARSETS['C'] = + exports.CHARSETS['5'] = { + '[': 'Ä', + '\\': 'Ö', + ']': 'Å', + '^': 'Ü', + '`': 'é', + '{': 'ä', + '|': 'ö', + '}': 'å', + '~': 'ü' + }; +exports.CHARSETS['R'] = { + '#': '£', + '@': 'à', + '[': '°', + '\\': 'ç', + ']': '§', + '{': 'é', + '|': 'ù', + '}': 'è', + '~': '¨' +}; +exports.CHARSETS['Q'] = { + '@': 'à', + '[': 'â', + '\\': 'ç', + ']': 'ê', + '^': 'î', + '`': 'ô', + '{': 'é', + '|': 'ù', + '}': 'è', + '~': 'û' +}; +exports.CHARSETS['K'] = { + '@': '§', + '[': 'Ä', + '\\': 'Ö', + ']': 'Ü', + '{': 'ä', + '|': 'ö', + '}': 'ü', + '~': 'ß' +}; +exports.CHARSETS['Y'] = { + '#': '£', + '@': '§', + '[': '°', + '\\': 'ç', + ']': 'é', + '`': 'ù', + '{': 'à', + '|': 'ò', + '}': 'è', + '~': 'ì' +}; +exports.CHARSETS['E'] = + exports.CHARSETS['6'] = { + '@': 'Ä', + '[': 'Æ', + '\\': 'Ø', + ']': 'Å', + '^': 'Ü', + '`': 'ä', + '{': 'æ', + '|': 'ø', + '}': 'å', + '~': 'ü' + }; +exports.CHARSETS['Z'] = { + '#': '£', + '@': '§', + '[': '¡', + '\\': 'Ñ', + ']': '¿', + '{': '°', + '|': 'ñ', + '}': 'ç' +}; +exports.CHARSETS['H'] = + exports.CHARSETS['7'] = { + '@': 'É', + '[': 'Ä', + '\\': 'Ö', + ']': 'Å', + '^': 'Ü', + '`': 'é', + '{': 'ä', + '|': 'ö', + '}': 'å', + '~': 'ü' + }; +exports.CHARSETS['='] = { + '#': 'ù', + '@': 'à', + '[': 'é', + '\\': 'ç', + ']': 'ê', + '^': 'î', + '_': 'è', + '`': 'ô', + '{': 'ä', + '|': 'ö', + '}': 'ü', + '~': 'û' +}; + + + +},{}],5:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var CompositionHelper = (function () { + function CompositionHelper(textarea, compositionView, terminal) { + this.textarea = textarea; + this.compositionView = compositionView; + this.terminal = terminal; + this.isComposing = false; + this.isSendingComposition = false; + this.compositionPosition = { start: null, end: null }; + } + CompositionHelper.prototype.compositionstart = function () { + this.isComposing = true; + this.compositionPosition.start = this.textarea.value.length; + this.compositionView.textContent = ''; + this.compositionView.classList.add('active'); + }; + CompositionHelper.prototype.compositionupdate = function (ev) { + var _this = this; + this.compositionView.textContent = ev.data; + this.updateCompositionElements(); + setTimeout(function () { + _this.compositionPosition.end = _this.textarea.value.length; + }, 0); + }; + CompositionHelper.prototype.compositionend = function () { + this.finalizeComposition(true); + }; + CompositionHelper.prototype.keydown = function (ev) { + if (this.isComposing || this.isSendingComposition) { + if (ev.keyCode === 229) { + return false; + } + else if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) { + return false; + } + else { + this.finalizeComposition(false); + } + } + if (ev.keyCode === 229) { + this.handleAnyTextareaChanges(); + return false; + } + return true; + }; + CompositionHelper.prototype.finalizeComposition = function (waitForPropogation) { + var _this = this; + this.compositionView.classList.remove('active'); + this.isComposing = false; + this.clearTextareaPosition(); + if (!waitForPropogation) { + this.isSendingComposition = false; + var input = this.textarea.value.substring(this.compositionPosition.start, this.compositionPosition.end); + this.terminal.handler(input); + } + else { + var currentCompositionPosition_1 = { + start: this.compositionPosition.start, + end: this.compositionPosition.end, + }; + this.isSendingComposition = true; + setTimeout(function () { + if (_this.isSendingComposition) { + _this.isSendingComposition = false; + var input = void 0; + if (_this.isComposing) { + input = _this.textarea.value.substring(currentCompositionPosition_1.start, currentCompositionPosition_1.end); + } + else { + input = _this.textarea.value.substring(currentCompositionPosition_1.start); + } + _this.terminal.handler(input); + } + }, 0); + } + }; + CompositionHelper.prototype.handleAnyTextareaChanges = function () { + var _this = this; + var oldValue = this.textarea.value; + setTimeout(function () { + if (!_this.isComposing) { + var newValue = _this.textarea.value; + var diff = newValue.replace(oldValue, ''); + if (diff.length > 0) { + _this.terminal.handler(diff); + } + } + }, 0); + }; + CompositionHelper.prototype.updateCompositionElements = function (dontRecurse) { + var _this = this; + if (!this.isComposing) { + return; + } + if (this.terminal.buffer.isCursorInViewport) { + var cellHeight = Math.ceil(this.terminal.charMeasure.height * this.terminal.options.lineHeight); + var cursorTop = this.terminal.buffer.y * cellHeight; + var cursorLeft = this.terminal.buffer.x * this.terminal.charMeasure.width; + this.compositionView.style.left = cursorLeft + 'px'; + this.compositionView.style.top = cursorTop + 'px'; + this.compositionView.style.height = cellHeight + 'px'; + this.compositionView.style.lineHeight = cellHeight + 'px'; + var compositionViewBounds = this.compositionView.getBoundingClientRect(); + this.textarea.style.left = cursorLeft + 'px'; + this.textarea.style.top = cursorTop + 'px'; + this.textarea.style.width = compositionViewBounds.width + 'px'; + this.textarea.style.height = compositionViewBounds.height + 'px'; + this.textarea.style.lineHeight = compositionViewBounds.height + 'px'; + } + if (!dontRecurse) { + setTimeout(function () { return _this.updateCompositionElements(true); }, 0); + } + }; + ; + CompositionHelper.prototype.clearTextareaPosition = function () { + this.textarea.style.left = ''; + this.textarea.style.top = ''; + }; + ; + return CompositionHelper; +}()); +exports.CompositionHelper = CompositionHelper; + + + +},{}],6:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var C0; +(function (C0) { + C0.NUL = '\x00'; + C0.SOH = '\x01'; + C0.STX = '\x02'; + C0.ETX = '\x03'; + C0.EOT = '\x04'; + C0.ENQ = '\x05'; + C0.ACK = '\x06'; + C0.BEL = '\x07'; + C0.BS = '\x08'; + C0.HT = '\x09'; + C0.LF = '\x0a'; + C0.VT = '\x0b'; + C0.FF = '\x0c'; + C0.CR = '\x0d'; + C0.SO = '\x0e'; + C0.SI = '\x0f'; + C0.DLE = '\x10'; + C0.DC1 = '\x11'; + C0.DC2 = '\x12'; + C0.DC3 = '\x13'; + C0.DC4 = '\x14'; + C0.NAK = '\x15'; + C0.SYN = '\x16'; + C0.ETB = '\x17'; + C0.CAN = '\x18'; + C0.EM = '\x19'; + C0.SUB = '\x1a'; + C0.ESC = '\x1b'; + C0.FS = '\x1c'; + C0.GS = '\x1d'; + C0.RS = '\x1e'; + C0.US = '\x1f'; + C0.SP = '\x20'; + C0.DEL = '\x7f'; +})(C0 = exports.C0 || (exports.C0 = {})); +; + + + +},{}],7:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var EventEmitter = (function () { + function EventEmitter() { + this._events = this._events || {}; + } + EventEmitter.prototype.on = function (type, listener) { + this._events[type] = this._events[type] || []; + this._events[type].push(listener); + }; + EventEmitter.prototype.off = function (type, listener) { + if (!this._events[type]) { + return; + } + var obj = this._events[type]; + var i = obj.length; + while (i--) { + if (obj[i] === listener || obj[i].listener === listener) { + obj.splice(i, 1); + return; + } + } + }; + EventEmitter.prototype.removeAllListeners = function (type) { + if (this._events[type]) { + delete this._events[type]; + } + }; + EventEmitter.prototype.once = function (type, listener) { + function on() { + var args = Array.prototype.slice.call(arguments); + this.off(type, on); + listener.apply(this, args); + } + on.listener = listener; + this.on(type, on); + }; + EventEmitter.prototype.emit = function (type) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + if (!this._events[type]) { + return; + } + var obj = this._events[type]; + for (var i = 0; i < obj.length; i++) { + obj[i].apply(this, args); + } + }; + EventEmitter.prototype.listeners = function (type) { + return this._events[type] || []; + }; + EventEmitter.prototype.destroy = function () { + this._events = {}; + }; + return EventEmitter; +}()); +exports.EventEmitter = EventEmitter; + + + +},{}],8:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var EscapeSequences_1 = require("./EscapeSequences"); +var Charsets_1 = require("./Charsets"); +var Buffer_1 = require("./Buffer"); +var Types_1 = require("./renderer/Types"); +var CharWidth_1 = require("./CharWidth"); +var InputHandler = (function () { + function InputHandler(_terminal) { + this._terminal = _terminal; + } + InputHandler.prototype.addChar = function (char, code) { + if (char >= ' ') { + var ch_width = CharWidth_1.wcwidth(code); + if (this._terminal.charset && this._terminal.charset[char]) { + char = this._terminal.charset[char]; + } + var row = this._terminal.buffer.y + this._terminal.buffer.ybase; + if (!ch_width && this._terminal.buffer.x) { + if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1]) { + if (!this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][Buffer_1.CHAR_DATA_WIDTH_INDEX]) { + if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2]) { + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2][Buffer_1.CHAR_DATA_CHAR_INDEX] += char; + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2][3] = char.charCodeAt(0); + } + } + else { + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][Buffer_1.CHAR_DATA_CHAR_INDEX] += char; + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][3] = char.charCodeAt(0); + } + this._terminal.updateRange(this._terminal.buffer.y); + } + return; + } + if (this._terminal.buffer.x + ch_width - 1 >= this._terminal.cols) { + if (this._terminal.wraparoundMode) { + this._terminal.buffer.x = 0; + this._terminal.buffer.y++; + if (this._terminal.buffer.y > this._terminal.buffer.scrollBottom) { + this._terminal.buffer.y--; + this._terminal.scroll(true); + } + else { + this._terminal.buffer.lines.get(this._terminal.buffer.y).isWrapped = true; + } + } + else { + if (ch_width === 2) + return; + } + } + row = this._terminal.buffer.y + this._terminal.buffer.ybase; + if (this._terminal.insertMode) { + for (var moves = 0; moves < ch_width; ++moves) { + var removed = this._terminal.buffer.lines.get(this._terminal.buffer.y + this._terminal.buffer.ybase).pop(); + if (removed[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0 + && this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] + && this._terminal.buffer.lines.get(row)[this._terminal.cols - 2][Buffer_1.CHAR_DATA_WIDTH_INDEX] === 2) { + this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] = [this._terminal.curAttr, ' ', 1, ' '.charCodeAt(0)]; + } + this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 0, [this._terminal.curAttr, ' ', 1, ' '.charCodeAt(0)]); + } + } + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, char, ch_width, char.charCodeAt(0)]; + this._terminal.buffer.x++; + this._terminal.updateRange(this._terminal.buffer.y); + if (ch_width === 2) { + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, '', 0, undefined]; + this._terminal.buffer.x++; + } + } + }; + InputHandler.prototype.bell = function () { + this._terminal.bell(); + }; + InputHandler.prototype.lineFeed = function () { + if (this._terminal.convertEol) { + this._terminal.buffer.x = 0; + } + this._terminal.buffer.y++; + if (this._terminal.buffer.y > this._terminal.buffer.scrollBottom) { + this._terminal.buffer.y--; + this._terminal.scroll(); + } + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x--; + } + this._terminal.emit('linefeed'); + }; + InputHandler.prototype.carriageReturn = function () { + this._terminal.buffer.x = 0; + }; + InputHandler.prototype.backspace = function () { + if (this._terminal.buffer.x > 0) { + this._terminal.buffer.x--; + } + }; + InputHandler.prototype.tab = function () { + this._terminal.buffer.x = this._terminal.buffer.nextStop(); + }; + InputHandler.prototype.shiftOut = function () { + this._terminal.setgLevel(1); + }; + InputHandler.prototype.shiftIn = function () { + this._terminal.setgLevel(0); + }; + InputHandler.prototype.insertChars = function (params) { + var param = params[0]; + if (param < 1) + param = 1; + var row = this._terminal.buffer.y + this._terminal.buffer.ybase; + var j = this._terminal.buffer.x; + var ch = [this._terminal.eraseAttr(), ' ', 1, 32]; + while (param-- && j < this._terminal.cols) { + this._terminal.buffer.lines.get(row).splice(j++, 0, ch); + this._terminal.buffer.lines.get(row).pop(); + } + }; + InputHandler.prototype.cursorUp = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y -= param; + if (this._terminal.buffer.y < 0) { + this._terminal.buffer.y = 0; + } + }; + InputHandler.prototype.cursorDown = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y += param; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x--; + } + }; + InputHandler.prototype.cursorForward = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.x += param; + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x = this._terminal.cols - 1; + } + }; + InputHandler.prototype.cursorBackward = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x--; + } + this._terminal.buffer.x -= param; + if (this._terminal.buffer.x < 0) { + this._terminal.buffer.x = 0; + } + }; + InputHandler.prototype.cursorNextLine = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y += param; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + this._terminal.buffer.x = 0; + }; + InputHandler.prototype.cursorPrecedingLine = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y -= param; + if (this._terminal.buffer.y < 0) { + this._terminal.buffer.y = 0; + } + this._terminal.buffer.x = 0; + }; + InputHandler.prototype.cursorCharAbsolute = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.x = param - 1; + }; + InputHandler.prototype.cursorPosition = function (params) { + var col; + var row = params[0] - 1; + if (params.length >= 2) { + col = params[1] - 1; + } + else { + col = 0; + } + if (row < 0) { + row = 0; + } + else if (row >= this._terminal.rows) { + row = this._terminal.rows - 1; + } + if (col < 0) { + col = 0; + } + else if (col >= this._terminal.cols) { + col = this._terminal.cols - 1; + } + this._terminal.buffer.x = col; + this._terminal.buffer.y = row; + }; + InputHandler.prototype.cursorForwardTab = function (params) { + var param = params[0] || 1; + while (param--) { + this._terminal.buffer.x = this._terminal.buffer.nextStop(); + } + }; + InputHandler.prototype.eraseInDisplay = function (params) { + var j; + switch (params[0]) { + case 0: + this._terminal.eraseRight(this._terminal.buffer.x, this._terminal.buffer.y); + j = this._terminal.buffer.y + 1; + for (; j < this._terminal.rows; j++) { + this._terminal.eraseLine(j); + } + break; + case 1: + this._terminal.eraseLeft(this._terminal.buffer.x, this._terminal.buffer.y); + j = this._terminal.buffer.y; + while (j--) { + this._terminal.eraseLine(j); + } + break; + case 2: + j = this._terminal.rows; + while (j--) + this._terminal.eraseLine(j); + break; + case 3: + var scrollBackSize = this._terminal.buffer.lines.length - this._terminal.rows; + if (scrollBackSize > 0) { + this._terminal.buffer.lines.trimStart(scrollBackSize); + this._terminal.buffer.ybase = Math.max(this._terminal.buffer.ybase - scrollBackSize, 0); + this._terminal.buffer.ydisp = Math.max(this._terminal.buffer.ydisp - scrollBackSize, 0); + this._terminal.emit('scroll', 0); + } + break; + } + }; + InputHandler.prototype.eraseInLine = function (params) { + switch (params[0]) { + case 0: + this._terminal.eraseRight(this._terminal.buffer.x, this._terminal.buffer.y); + break; + case 1: + this._terminal.eraseLeft(this._terminal.buffer.x, this._terminal.buffer.y); + break; + case 2: + this._terminal.eraseLine(this._terminal.buffer.y); + break; + } + }; + InputHandler.prototype.insertLines = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + var row = this._terminal.buffer.y + this._terminal.buffer.ybase; + var scrollBottomRowsOffset = this._terminal.rows - 1 - this._terminal.buffer.scrollBottom; + var scrollBottomAbsolute = this._terminal.rows - 1 + this._terminal.buffer.ybase - scrollBottomRowsOffset + 1; + while (param--) { + this._terminal.buffer.lines.splice(scrollBottomAbsolute - 1, 1); + this._terminal.buffer.lines.splice(row, 0, this._terminal.blankLine(true)); + } + this._terminal.updateRange(this._terminal.buffer.y); + this._terminal.updateRange(this._terminal.buffer.scrollBottom); + }; + InputHandler.prototype.deleteLines = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + var row = this._terminal.buffer.y + this._terminal.buffer.ybase; + var j; + j = this._terminal.rows - 1 - this._terminal.buffer.scrollBottom; + j = this._terminal.rows - 1 + this._terminal.buffer.ybase - j; + while (param--) { + this._terminal.buffer.lines.splice(row, 1); + this._terminal.buffer.lines.splice(j, 0, this._terminal.blankLine(true)); + } + this._terminal.updateRange(this._terminal.buffer.y); + this._terminal.updateRange(this._terminal.buffer.scrollBottom); + }; + InputHandler.prototype.deleteChars = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + var row = this._terminal.buffer.y + this._terminal.buffer.ybase; + var ch = [this._terminal.eraseAttr(), ' ', 1, 32]; + while (param--) { + this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 1); + this._terminal.buffer.lines.get(row).push(ch); + } + this._terminal.updateRange(this._terminal.buffer.y); + }; + InputHandler.prototype.scrollUp = function (params) { + var param = params[0] || 1; + while (param--) { + this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollTop, 1); + this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollBottom, 0, this._terminal.blankLine()); + } + this._terminal.updateRange(this._terminal.buffer.scrollTop); + this._terminal.updateRange(this._terminal.buffer.scrollBottom); + }; + InputHandler.prototype.scrollDown = function (params) { + var param = params[0] || 1; + while (param--) { + this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollBottom, 1); + this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollTop, 0, this._terminal.blankLine()); + } + this._terminal.updateRange(this._terminal.buffer.scrollTop); + this._terminal.updateRange(this._terminal.buffer.scrollBottom); + }; + InputHandler.prototype.eraseChars = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + var row = this._terminal.buffer.y + this._terminal.buffer.ybase; + var j = this._terminal.buffer.x; + var ch = [this._terminal.eraseAttr(), ' ', 1, 32]; + while (param-- && j < this._terminal.cols) { + this._terminal.buffer.lines.get(row)[j++] = ch; + } + }; + InputHandler.prototype.cursorBackwardTab = function (params) { + var param = params[0] || 1; + while (param--) { + this._terminal.buffer.x = this._terminal.buffer.prevStop(); + } + }; + InputHandler.prototype.charPosAbsolute = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.x = param - 1; + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x = this._terminal.cols - 1; + } + }; + InputHandler.prototype.HPositionRelative = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.x += param; + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x = this._terminal.cols - 1; + } + }; + InputHandler.prototype.repeatPrecedingCharacter = function (params) { + var param = params[0] || 1; + var line = this._terminal.buffer.lines.get(this._terminal.buffer.ybase + this._terminal.buffer.y); + var ch = line[this._terminal.buffer.x - 1] || [this._terminal.defAttr, ' ', 1, 32]; + while (param--) { + line[this._terminal.buffer.x++] = ch; + } + }; + InputHandler.prototype.sendDeviceAttributes = function (params) { + if (params[0] > 0) { + return; + } + if (!this._terminal.prefix) { + if (this._terminal.is('xterm') || this._terminal.is('rxvt-unicode') || this._terminal.is('screen')) { + this._terminal.send(EscapeSequences_1.C0.ESC + '[?1;2c'); + } + else if (this._terminal.is('linux')) { + this._terminal.send(EscapeSequences_1.C0.ESC + '[?6c'); + } + } + else if (this._terminal.prefix === '>') { + if (this._terminal.is('xterm')) { + this._terminal.send(EscapeSequences_1.C0.ESC + '[>0;276;0c'); + } + else if (this._terminal.is('rxvt-unicode')) { + this._terminal.send(EscapeSequences_1.C0.ESC + '[>85;95;0c'); + } + else if (this._terminal.is('linux')) { + this._terminal.send(params[0] + 'c'); + } + else if (this._terminal.is('screen')) { + this._terminal.send(EscapeSequences_1.C0.ESC + '[>83;40003;0c'); + } + } + }; + InputHandler.prototype.linePosAbsolute = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y = param - 1; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + }; + InputHandler.prototype.VPositionRelative = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y += param; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x--; + } + }; + InputHandler.prototype.HVPosition = function (params) { + if (params[0] < 1) + params[0] = 1; + if (params[1] < 1) + params[1] = 1; + this._terminal.buffer.y = params[0] - 1; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + this._terminal.buffer.x = params[1] - 1; + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x = this._terminal.cols - 1; + } + }; + InputHandler.prototype.tabClear = function (params) { + var param = params[0]; + if (param <= 0) { + delete this._terminal.buffer.tabs[this._terminal.buffer.x]; + } + else if (param === 3) { + this._terminal.buffer.tabs = {}; + } + }; + InputHandler.prototype.setMode = function (params) { + if (params.length > 1) { + for (var i = 0; i < params.length; i++) { + this.setMode([params[i]]); + } + return; + } + if (!this._terminal.prefix) { + switch (params[0]) { + case 4: + this._terminal.insertMode = true; + break; + case 20: + break; + } + } + else if (this._terminal.prefix === '?') { + switch (params[0]) { + case 1: + this._terminal.applicationCursor = true; + break; + case 2: + this._terminal.setgCharset(0, Charsets_1.DEFAULT_CHARSET); + this._terminal.setgCharset(1, Charsets_1.DEFAULT_CHARSET); + this._terminal.setgCharset(2, Charsets_1.DEFAULT_CHARSET); + this._terminal.setgCharset(3, Charsets_1.DEFAULT_CHARSET); + break; + case 3: + this._terminal.savedCols = this._terminal.cols; + this._terminal.resize(132, this._terminal.rows); + break; + case 6: + this._terminal.originMode = true; + break; + case 7: + this._terminal.wraparoundMode = true; + break; + case 12: + break; + case 66: + this._terminal.log('Serial port requested application keypad.'); + this._terminal.applicationKeypad = true; + this._terminal.viewport.syncScrollArea(); + break; + case 9: + case 1000: + case 1002: + case 1003: + this._terminal.x10Mouse = params[0] === 9; + this._terminal.vt200Mouse = params[0] === 1000; + this._terminal.normalMouse = params[0] > 1000; + this._terminal.mouseEvents = true; + this._terminal.element.classList.add('enable-mouse-events'); + this._terminal.selectionManager.disable(); + this._terminal.log('Binding to mouse events.'); + break; + case 1004: + this._terminal.sendFocus = true; + break; + case 1005: + this._terminal.utfMouse = true; + break; + case 1006: + this._terminal.sgrMouse = true; + break; + case 1015: + this._terminal.urxvtMouse = true; + break; + case 25: + this._terminal.cursorHidden = false; + break; + case 1049: + case 47: + case 1047: + this._terminal.buffers.activateAltBuffer(); + this._terminal.selectionManager.setBuffer(this._terminal.buffer); + this._terminal.viewport.syncScrollArea(); + this._terminal.showCursor(); + break; + case 2004: + this._terminal.bracketedPasteMode = true; + break; + } + } + }; + InputHandler.prototype.resetMode = function (params) { + if (params.length > 1) { + for (var i = 0; i < params.length; i++) { + this.resetMode([params[i]]); + } + return; + } + if (!this._terminal.prefix) { + switch (params[0]) { + case 4: + this._terminal.insertMode = false; + break; + case 20: + break; + } + } + else if (this._terminal.prefix === '?') { + switch (params[0]) { + case 1: + this._terminal.applicationCursor = false; + break; + case 3: + if (this._terminal.cols === 132 && this._terminal.savedCols) { + this._terminal.resize(this._terminal.savedCols, this._terminal.rows); + } + delete this._terminal.savedCols; + break; + case 6: + this._terminal.originMode = false; + break; + case 7: + this._terminal.wraparoundMode = false; + break; + case 12: + break; + case 66: + this._terminal.log('Switching back to normal keypad.'); + this._terminal.applicationKeypad = false; + this._terminal.viewport.syncScrollArea(); + break; + case 9: + case 1000: + case 1002: + case 1003: + this._terminal.x10Mouse = false; + this._terminal.vt200Mouse = false; + this._terminal.normalMouse = false; + this._terminal.mouseEvents = false; + this._terminal.element.classList.remove('enable-mouse-events'); + this._terminal.selectionManager.enable(); + break; + case 1004: + this._terminal.sendFocus = false; + break; + case 1005: + this._terminal.utfMouse = false; + break; + case 1006: + this._terminal.sgrMouse = false; + break; + case 1015: + this._terminal.urxvtMouse = false; + break; + case 25: + this._terminal.cursorHidden = true; + break; + case 1049: + case 47: + case 1047: + this._terminal.buffers.activateNormalBuffer(); + this._terminal.selectionManager.setBuffer(this._terminal.buffer); + this._terminal.refresh(0, this._terminal.rows - 1); + this._terminal.viewport.syncScrollArea(); + this._terminal.showCursor(); + break; + case 2004: + this._terminal.bracketedPasteMode = false; + break; + } + } + }; + InputHandler.prototype.charAttributes = function (params) { + if (params.length === 1 && params[0] === 0) { + this._terminal.curAttr = this._terminal.defAttr; + return; + } + var l = params.length; + var flags = this._terminal.curAttr >> 18; + var fg = (this._terminal.curAttr >> 9) & 0x1ff; + var bg = this._terminal.curAttr & 0x1ff; + var p; + for (var i = 0; i < l; i++) { + p = params[i]; + if (p >= 30 && p <= 37) { + fg = p - 30; + } + else if (p >= 40 && p <= 47) { + bg = p - 40; + } + else if (p >= 90 && p <= 97) { + p += 8; + fg = p - 90; + } + else if (p >= 100 && p <= 107) { + p += 8; + bg = p - 100; + } + else if (p === 0) { + flags = this._terminal.defAttr >> 18; + fg = (this._terminal.defAttr >> 9) & 0x1ff; + bg = this._terminal.defAttr & 0x1ff; + } + else if (p === 1) { + flags |= Types_1.FLAGS.BOLD; + } + else if (p === 4) { + flags |= Types_1.FLAGS.UNDERLINE; + } + else if (p === 5) { + flags |= Types_1.FLAGS.BLINK; + } + else if (p === 7) { + flags |= Types_1.FLAGS.INVERSE; + } + else if (p === 8) { + flags |= Types_1.FLAGS.INVISIBLE; + } + else if (p === 2) { + flags |= Types_1.FLAGS.DIM; + } + else if (p === 22) { + flags &= ~Types_1.FLAGS.BOLD; + flags &= ~Types_1.FLAGS.DIM; + } + else if (p === 24) { + flags &= ~Types_1.FLAGS.UNDERLINE; + } + else if (p === 25) { + flags &= ~Types_1.FLAGS.BLINK; + } + else if (p === 27) { + flags &= ~Types_1.FLAGS.INVERSE; + } + else if (p === 28) { + flags &= ~Types_1.FLAGS.INVISIBLE; + } + else if (p === 39) { + fg = (this._terminal.defAttr >> 9) & 0x1ff; + } + else if (p === 49) { + bg = this._terminal.defAttr & 0x1ff; + } + else if (p === 38) { + if (params[i + 1] === 2) { + i += 2; + fg = this._terminal.matchColor(params[i] & 0xff, params[i + 1] & 0xff, params[i + 2] & 0xff); + if (fg === -1) + fg = 0x1ff; + i += 2; + } + else if (params[i + 1] === 5) { + i += 2; + p = params[i] & 0xff; + fg = p; + } + } + else if (p === 48) { + if (params[i + 1] === 2) { + i += 2; + bg = this._terminal.matchColor(params[i] & 0xff, params[i + 1] & 0xff, params[i + 2] & 0xff); + if (bg === -1) + bg = 0x1ff; + i += 2; + } + else if (params[i + 1] === 5) { + i += 2; + p = params[i] & 0xff; + bg = p; + } + } + else if (p === 100) { + fg = (this._terminal.defAttr >> 9) & 0x1ff; + bg = this._terminal.defAttr & 0x1ff; + } + else { + this._terminal.error('Unknown SGR attribute: %d.', p); + } + } + this._terminal.curAttr = (flags << 18) | (fg << 9) | bg; + }; + InputHandler.prototype.deviceStatus = function (params) { + if (!this._terminal.prefix) { + switch (params[0]) { + case 5: + this._terminal.send(EscapeSequences_1.C0.ESC + '[0n'); + break; + case 6: + this._terminal.send(EscapeSequences_1.C0.ESC + '[' + + (this._terminal.buffer.y + 1) + + ';' + + (this._terminal.buffer.x + 1) + + 'R'); + break; + } + } + else if (this._terminal.prefix === '?') { + switch (params[0]) { + case 6: + this._terminal.send(EscapeSequences_1.C0.ESC + '[?' + + (this._terminal.buffer.y + 1) + + ';' + + (this._terminal.buffer.x + 1) + + 'R'); + break; + case 15: + break; + case 25: + break; + case 26: + break; + case 53: + break; + } + } + }; + InputHandler.prototype.softReset = function (params) { + this._terminal.cursorHidden = false; + this._terminal.insertMode = false; + this._terminal.originMode = false; + this._terminal.wraparoundMode = true; + this._terminal.applicationKeypad = false; + this._terminal.viewport.syncScrollArea(); + this._terminal.applicationCursor = false; + this._terminal.buffer.scrollTop = 0; + this._terminal.buffer.scrollBottom = this._terminal.rows - 1; + this._terminal.curAttr = this._terminal.defAttr; + this._terminal.buffer.x = this._terminal.buffer.y = 0; + this._terminal.charset = null; + this._terminal.glevel = 0; + this._terminal.charsets = [null]; + }; + InputHandler.prototype.setCursorStyle = function (params) { + var param = params[0] < 1 ? 1 : params[0]; + switch (param) { + case 1: + case 2: + this._terminal.setOption('cursorStyle', 'block'); + break; + case 3: + case 4: + this._terminal.setOption('cursorStyle', 'underline'); + break; + case 5: + case 6: + this._terminal.setOption('cursorStyle', 'bar'); + break; + } + var isBlinking = param % 2 === 1; + this._terminal.setOption('cursorBlink', isBlinking); + }; + InputHandler.prototype.setScrollRegion = function (params) { + if (this._terminal.prefix) + return; + this._terminal.buffer.scrollTop = (params[0] || 1) - 1; + this._terminal.buffer.scrollBottom = (params[1] && params[1] <= this._terminal.rows ? params[1] : this._terminal.rows) - 1; + this._terminal.buffer.x = 0; + this._terminal.buffer.y = 0; + }; + InputHandler.prototype.saveCursor = function (params) { + this._terminal.buffer.savedX = this._terminal.buffer.x; + this._terminal.buffer.savedY = this._terminal.buffer.y; + }; + InputHandler.prototype.restoreCursor = function (params) { + this._terminal.buffer.x = this._terminal.buffer.savedX || 0; + this._terminal.buffer.y = this._terminal.buffer.savedY || 0; + }; + return InputHandler; +}()); +exports.InputHandler = InputHandler; + + + +},{"./Buffer":1,"./CharWidth":3,"./Charsets":4,"./EscapeSequences":6,"./renderer/Types":27}],9:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Types_1 = require("./Types"); +var MouseZoneManager_1 = require("./input/MouseZoneManager"); +var EventEmitter_1 = require("./EventEmitter"); +var protocolClause = '(https?:\\/\\/)'; +var domainCharacterSet = '[\\da-z\\.-]+'; +var negatedDomainCharacterSet = '[^\\da-z\\.-]+'; +var domainBodyClause = '(' + domainCharacterSet + ')'; +var tldClause = '([a-z\\.]{2,6})'; +var ipClause = '((\\d{1,3}\\.){3}\\d{1,3})'; +var localHostClause = '(localhost)'; +var portClause = '(:\\d{1,5})'; +var hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?'; +var pathClause = '(\\/[\\/\\w\\.\\-%~]*)*'; +var queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*'; +var queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?'; +var hashFragmentClause = '(#' + queryStringHashFragmentCharacterSet + ')?'; +var negatedPathCharacterSet = '[^\\/\\w\\.\\-%]+'; +var bodyClause = hostClause + pathClause + queryStringClause + hashFragmentClause; +var start = '(?:^|' + negatedDomainCharacterSet + ')('; +var end = ')($|' + negatedPathCharacterSet + ')'; +var strictUrlRegex = new RegExp(start + protocolClause + bodyClause + end); +var HYPERTEXT_LINK_MATCHER_ID = 0; +var Linkifier = (function (_super) { + __extends(Linkifier, _super); + function Linkifier(_terminal) { + var _this = _super.call(this) || this; + _this._terminal = _terminal; + _this._linkMatchers = []; + _this._nextLinkMatcherId = HYPERTEXT_LINK_MATCHER_ID; + _this._rowsToLinkify = { + start: null, + end: null + }; + _this.registerLinkMatcher(strictUrlRegex, null, { matchIndex: 1 }); + return _this; + } + Linkifier.prototype.attachToDom = function (mouseZoneManager) { + this._mouseZoneManager = mouseZoneManager; + }; + Linkifier.prototype.linkifyRows = function (start, end) { + var _this = this; + if (!this._mouseZoneManager) { + return; + } + if (!this._rowsToLinkify.start) { + this._rowsToLinkify.start = start; + this._rowsToLinkify.end = end; + } + else { + this._rowsToLinkify.start = this._rowsToLinkify.start < start ? this._rowsToLinkify.start : start; + this._rowsToLinkify.end = this._rowsToLinkify.end > end ? this._rowsToLinkify.end : end; + } + this._mouseZoneManager.clearAll(start, end); + if (this._rowsTimeoutId) { + clearTimeout(this._rowsTimeoutId); + } + this._rowsTimeoutId = setTimeout(function () { return _this._linkifyRows(); }, Linkifier.TIME_BEFORE_LINKIFY); + }; + Linkifier.prototype._linkifyRows = function () { + this._rowsTimeoutId = null; + for (var i = this._rowsToLinkify.start; i <= this._rowsToLinkify.end; i++) { + this._linkifyRow(i); + } + this._rowsToLinkify.start = null; + this._rowsToLinkify.end = null; + }; + Linkifier.prototype.setHypertextLinkHandler = function (handler) { + this._linkMatchers[HYPERTEXT_LINK_MATCHER_ID].handler = handler; + }; + Linkifier.prototype.setHypertextValidationCallback = function (callback) { + this._linkMatchers[HYPERTEXT_LINK_MATCHER_ID].validationCallback = callback; + }; + Linkifier.prototype.registerLinkMatcher = function (regex, handler, options) { + if (options === void 0) { options = {}; } + if (this._nextLinkMatcherId !== HYPERTEXT_LINK_MATCHER_ID && !handler) { + throw new Error('handler must be defined'); + } + var matcher = { + id: this._nextLinkMatcherId++, + regex: regex, + handler: handler, + matchIndex: options.matchIndex, + validationCallback: options.validationCallback, + hoverTooltipCallback: options.tooltipCallback, + hoverLeaveCallback: options.leaveCallback, + priority: options.priority || 0 + }; + this._addLinkMatcherToList(matcher); + return matcher.id; + }; + Linkifier.prototype._addLinkMatcherToList = function (matcher) { + if (this._linkMatchers.length === 0) { + this._linkMatchers.push(matcher); + return; + } + for (var i = this._linkMatchers.length - 1; i >= 0; i--) { + if (matcher.priority <= this._linkMatchers[i].priority) { + this._linkMatchers.splice(i + 1, 0, matcher); + return; + } + } + this._linkMatchers.splice(0, 0, matcher); + }; + Linkifier.prototype.deregisterLinkMatcher = function (matcherId) { + for (var i = 1; i < this._linkMatchers.length; i++) { + if (this._linkMatchers[i].id === matcherId) { + this._linkMatchers.splice(i, 1); + return true; + } + } + return false; + }; + Linkifier.prototype._linkifyRow = function (rowIndex) { + var absoluteRowIndex = this._terminal.buffer.ydisp + rowIndex; + if (absoluteRowIndex >= this._terminal.buffer.lines.length) { + return; + } + var text = this._terminal.buffer.translateBufferLineToString(absoluteRowIndex, false); + for (var i = 0; i < this._linkMatchers.length; i++) { + this._doLinkifyRow(rowIndex, text, this._linkMatchers[i]); + } + }; + Linkifier.prototype._doLinkifyRow = function (rowIndex, text, matcher, offset) { + var _this = this; + if (offset === void 0) { offset = 0; } + var result = []; + var isHttpLinkMatcher = matcher.id === HYPERTEXT_LINK_MATCHER_ID; + var match = text.match(matcher.regex); + if (!match || match.length === 0) { + return; + } + var uri = match[typeof matcher.matchIndex !== 'number' ? 0 : matcher.matchIndex]; + var index = text.indexOf(uri); + if (matcher.validationCallback) { + matcher.validationCallback(uri, function (isValid) { + if (_this._rowsTimeoutId) { + return; + } + if (isValid) { + _this._addLink(offset + index, rowIndex, uri, matcher); + } + }); + } + else { + this._addLink(offset + index, rowIndex, uri, matcher); + } + var remainingStartIndex = index + uri.length; + var remainingText = text.substr(remainingStartIndex); + if (remainingText.length > 0) { + this._doLinkifyRow(rowIndex, remainingText, matcher, offset + remainingStartIndex); + } + }; + Linkifier.prototype._addLink = function (x, y, uri, matcher) { + var _this = this; + this._mouseZoneManager.add(new MouseZoneManager_1.MouseZone(x + 1, x + 1 + uri.length, y + 1, function (e) { + if (matcher.handler) { + return matcher.handler(e, uri); + } + window.open(uri, '_blank'); + }, function (e) { + _this.emit(Types_1.LinkHoverEventTypes.HOVER, { x: x, y: y, length: uri.length }); + _this._terminal.element.style.cursor = 'pointer'; + }, function (e) { + _this.emit(Types_1.LinkHoverEventTypes.TOOLTIP, { x: x, y: y, length: uri.length }); + if (matcher.hoverTooltipCallback) { + matcher.hoverTooltipCallback(e, uri); + } + }, function () { + _this.emit(Types_1.LinkHoverEventTypes.LEAVE, { x: x, y: y, length: uri.length }); + _this._terminal.element.style.cursor = ''; + if (matcher.hoverLeaveCallback) { + matcher.hoverLeaveCallback(); + } + })); + }; + Linkifier.TIME_BEFORE_LINKIFY = 200; + return Linkifier; +}(EventEmitter_1.EventEmitter)); +exports.Linkifier = Linkifier; + + + +},{"./EventEmitter":7,"./Types":14,"./input/MouseZoneManager":17}],10:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var EscapeSequences_1 = require("./EscapeSequences"); +var Charsets_1 = require("./Charsets"); +var normalStateHandler = {}; +normalStateHandler[EscapeSequences_1.C0.BEL] = function (parser, handler) { return handler.bell(); }; +normalStateHandler[EscapeSequences_1.C0.LF] = function (parser, handler) { return handler.lineFeed(); }; +normalStateHandler[EscapeSequences_1.C0.VT] = normalStateHandler[EscapeSequences_1.C0.LF]; +normalStateHandler[EscapeSequences_1.C0.FF] = normalStateHandler[EscapeSequences_1.C0.LF]; +normalStateHandler[EscapeSequences_1.C0.CR] = function (parser, handler) { return handler.carriageReturn(); }; +normalStateHandler[EscapeSequences_1.C0.BS] = function (parser, handler) { return handler.backspace(); }; +normalStateHandler[EscapeSequences_1.C0.HT] = function (parser, handler) { return handler.tab(); }; +normalStateHandler[EscapeSequences_1.C0.SO] = function (parser, handler) { return handler.shiftOut(); }; +normalStateHandler[EscapeSequences_1.C0.SI] = function (parser, handler) { return handler.shiftIn(); }; +normalStateHandler[EscapeSequences_1.C0.ESC] = function (parser, handler) { return parser.setState(ParserState.ESCAPED); }; +var escapedStateHandler = {}; +escapedStateHandler['['] = function (parser, terminal) { + terminal.params = []; + terminal.currentParam = 0; + parser.setState(ParserState.CSI_PARAM); +}; +escapedStateHandler[']'] = function (parser, terminal) { + terminal.params = []; + terminal.currentParam = 0; + parser.setState(ParserState.OSC); +}; +escapedStateHandler['P'] = function (parser, terminal) { + terminal.params = []; + terminal.currentParam = 0; + parser.setState(ParserState.DCS); +}; +escapedStateHandler['_'] = function (parser, terminal) { + parser.setState(ParserState.IGNORE); +}; +escapedStateHandler['^'] = function (parser, terminal) { + parser.setState(ParserState.IGNORE); +}; +escapedStateHandler['c'] = function (parser, terminal) { + terminal.reset(); +}; +escapedStateHandler['E'] = function (parser, terminal) { + terminal.buffer.x = 0; + terminal.index(); + parser.setState(ParserState.NORMAL); +}; +escapedStateHandler['D'] = function (parser, terminal) { + terminal.index(); + parser.setState(ParserState.NORMAL); +}; +escapedStateHandler['M'] = function (parser, terminal) { + terminal.reverseIndex(); + parser.setState(ParserState.NORMAL); +}; +escapedStateHandler['%'] = function (parser, terminal) { + terminal.setgLevel(0); + terminal.setgCharset(0, Charsets_1.DEFAULT_CHARSET); + parser.setState(ParserState.NORMAL); + parser.skipNextChar(); +}; +escapedStateHandler[EscapeSequences_1.C0.CAN] = function (parser) { return parser.setState(ParserState.NORMAL); }; +var csiParamStateHandler = {}; +csiParamStateHandler['?'] = function (parser) { return parser.setPrefix('?'); }; +csiParamStateHandler['>'] = function (parser) { return parser.setPrefix('>'); }; +csiParamStateHandler['!'] = function (parser) { return parser.setPrefix('!'); }; +csiParamStateHandler['0'] = function (parser) { return parser.setParam(parser.getParam() * 10); }; +csiParamStateHandler['1'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 1); }; +csiParamStateHandler['2'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 2); }; +csiParamStateHandler['3'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 3); }; +csiParamStateHandler['4'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 4); }; +csiParamStateHandler['5'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 5); }; +csiParamStateHandler['6'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 6); }; +csiParamStateHandler['7'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 7); }; +csiParamStateHandler['8'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 8); }; +csiParamStateHandler['9'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 9); }; +csiParamStateHandler['$'] = function (parser) { return parser.setPostfix('$'); }; +csiParamStateHandler['"'] = function (parser) { return parser.setPostfix('"'); }; +csiParamStateHandler[' '] = function (parser) { return parser.setPostfix(' '); }; +csiParamStateHandler['\''] = function (parser) { return parser.setPostfix('\''); }; +csiParamStateHandler[';'] = function (parser) { return parser.finalizeParam(); }; +csiParamStateHandler[EscapeSequences_1.C0.CAN] = function (parser) { return parser.setState(ParserState.NORMAL); }; +var csiStateHandler = {}; +csiStateHandler['@'] = function (handler, params, prefix) { return handler.insertChars(params); }; +csiStateHandler['A'] = function (handler, params, prefix) { return handler.cursorUp(params); }; +csiStateHandler['B'] = function (handler, params, prefix) { return handler.cursorDown(params); }; +csiStateHandler['C'] = function (handler, params, prefix) { return handler.cursorForward(params); }; +csiStateHandler['D'] = function (handler, params, prefix) { return handler.cursorBackward(params); }; +csiStateHandler['E'] = function (handler, params, prefix) { return handler.cursorNextLine(params); }; +csiStateHandler['F'] = function (handler, params, prefix) { return handler.cursorPrecedingLine(params); }; +csiStateHandler['G'] = function (handler, params, prefix) { return handler.cursorCharAbsolute(params); }; +csiStateHandler['H'] = function (handler, params, prefix) { return handler.cursorPosition(params); }; +csiStateHandler['I'] = function (handler, params, prefix) { return handler.cursorForwardTab(params); }; +csiStateHandler['J'] = function (handler, params, prefix) { return handler.eraseInDisplay(params); }; +csiStateHandler['K'] = function (handler, params, prefix) { return handler.eraseInLine(params); }; +csiStateHandler['L'] = function (handler, params, prefix) { return handler.insertLines(params); }; +csiStateHandler['M'] = function (handler, params, prefix) { return handler.deleteLines(params); }; +csiStateHandler['P'] = function (handler, params, prefix) { return handler.deleteChars(params); }; +csiStateHandler['S'] = function (handler, params, prefix) { return handler.scrollUp(params); }; +csiStateHandler['T'] = function (handler, params, prefix) { + if (params.length < 2 && !prefix) { + handler.scrollDown(params); + } +}; +csiStateHandler['X'] = function (handler, params, prefix) { return handler.eraseChars(params); }; +csiStateHandler['Z'] = function (handler, params, prefix) { return handler.cursorBackwardTab(params); }; +csiStateHandler['`'] = function (handler, params, prefix) { return handler.charPosAbsolute(params); }; +csiStateHandler['a'] = function (handler, params, prefix) { return handler.HPositionRelative(params); }; +csiStateHandler['b'] = function (handler, params, prefix) { return handler.repeatPrecedingCharacter(params); }; +csiStateHandler['c'] = function (handler, params, prefix) { return handler.sendDeviceAttributes(params); }; +csiStateHandler['d'] = function (handler, params, prefix) { return handler.linePosAbsolute(params); }; +csiStateHandler['e'] = function (handler, params, prefix) { return handler.VPositionRelative(params); }; +csiStateHandler['f'] = function (handler, params, prefix) { return handler.HVPosition(params); }; +csiStateHandler['g'] = function (handler, params, prefix) { return handler.tabClear(params); }; +csiStateHandler['h'] = function (handler, params, prefix) { return handler.setMode(params); }; +csiStateHandler['l'] = function (handler, params, prefix) { return handler.resetMode(params); }; +csiStateHandler['m'] = function (handler, params, prefix) { return handler.charAttributes(params); }; +csiStateHandler['n'] = function (handler, params, prefix) { return handler.deviceStatus(params); }; +csiStateHandler['p'] = function (handler, params, prefix) { + switch (prefix) { + case '!': + handler.softReset(params); + break; + } +}; +csiStateHandler['q'] = function (handler, params, prefix, postfix) { + if (postfix === ' ') { + handler.setCursorStyle(params); + } +}; +csiStateHandler['r'] = function (handler, params) { return handler.setScrollRegion(params); }; +csiStateHandler['s'] = function (handler, params) { return handler.saveCursor(params); }; +csiStateHandler['u'] = function (handler, params) { return handler.restoreCursor(params); }; +csiStateHandler[EscapeSequences_1.C0.CAN] = function (handler, params, prefix, postfix, parser) { return parser.setState(ParserState.NORMAL); }; +var ParserState; +(function (ParserState) { + ParserState[ParserState["NORMAL"] = 0] = "NORMAL"; + ParserState[ParserState["ESCAPED"] = 1] = "ESCAPED"; + ParserState[ParserState["CSI_PARAM"] = 2] = "CSI_PARAM"; + ParserState[ParserState["CSI"] = 3] = "CSI"; + ParserState[ParserState["OSC"] = 4] = "OSC"; + ParserState[ParserState["CHARSET"] = 5] = "CHARSET"; + ParserState[ParserState["DCS"] = 6] = "DCS"; + ParserState[ParserState["IGNORE"] = 7] = "IGNORE"; +})(ParserState = exports.ParserState || (exports.ParserState = {})); +var Parser = (function () { + function Parser(_inputHandler, _terminal) { + this._inputHandler = _inputHandler; + this._terminal = _terminal; + this._state = ParserState.NORMAL; + } + Parser.prototype.parse = function (data) { + var l = data.length; + var j; + var cs; + var ch; + var code; + var low; + var cursorStartX = this._terminal.buffer.x; + var cursorStartY = this._terminal.buffer.y; + if (this._terminal.debug) { + this._terminal.log('data: ' + data); + } + this._position = 0; + if (this._terminal.surrogate_high) { + data = this._terminal.surrogate_high + data; + this._terminal.surrogate_high = ''; + } + for (; this._position < l; this._position++) { + ch = data[this._position]; + code = data.charCodeAt(this._position); + if (0xD800 <= code && code <= 0xDBFF) { + low = data.charCodeAt(this._position + 1); + if (isNaN(low)) { + this._terminal.surrogate_high = ch; + continue; + } + code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000; + ch += data.charAt(this._position + 1); + } + if (0xDC00 <= code && code <= 0xDFFF) + continue; + switch (this._state) { + case ParserState.NORMAL: + if (ch in normalStateHandler) { + normalStateHandler[ch](this, this._inputHandler); + } + else { + this._inputHandler.addChar(ch, code); + } + break; + case ParserState.ESCAPED: + if (ch in escapedStateHandler) { + escapedStateHandler[ch](this, this._terminal); + break; + } + switch (ch) { + case '(': + case ')': + case '*': + case '+': + case '-': + case '.': + switch (ch) { + case '(': + this._terminal.gcharset = 0; + break; + case ')': + this._terminal.gcharset = 1; + break; + case '*': + this._terminal.gcharset = 2; + break; + case '+': + this._terminal.gcharset = 3; + break; + case '-': + this._terminal.gcharset = 1; + break; + case '.': + this._terminal.gcharset = 2; + break; + } + this._state = ParserState.CHARSET; + break; + case '/': + this._terminal.gcharset = 3; + this._state = ParserState.CHARSET; + this._position--; + break; + case 'N': + this._state = ParserState.NORMAL; + break; + case 'O': + this._state = ParserState.NORMAL; + break; + case 'n': + this._terminal.setgLevel(2); + this._state = ParserState.NORMAL; + break; + case 'o': + this._terminal.setgLevel(3); + this._state = ParserState.NORMAL; + break; + case '|': + this._terminal.setgLevel(3); + this._state = ParserState.NORMAL; + break; + case '}': + this._terminal.setgLevel(2); + this._state = ParserState.NORMAL; + break; + case '~': + this._terminal.setgLevel(1); + this._state = ParserState.NORMAL; + break; + case '7': + this._inputHandler.saveCursor(); + this._state = ParserState.NORMAL; + break; + case '8': + this._inputHandler.restoreCursor(); + this._state = ParserState.NORMAL; + break; + case '#': + this._state = ParserState.NORMAL; + this._position++; + break; + case 'H': + this._terminal.tabSet(); + this._state = ParserState.NORMAL; + break; + case '=': + this._terminal.log('Serial port requested application keypad.'); + this._terminal.applicationKeypad = true; + if (this._terminal.viewport) { + this._terminal.viewport.syncScrollArea(); + } + this._state = ParserState.NORMAL; + break; + case '>': + this._terminal.log('Switching back to normal keypad.'); + this._terminal.applicationKeypad = false; + if (this._terminal.viewport) { + this._terminal.viewport.syncScrollArea(); + } + this._state = ParserState.NORMAL; + break; + default: + this._state = ParserState.NORMAL; + this._terminal.error('Unknown ESC control: %s.', ch); + break; + } + break; + case ParserState.CHARSET: + if (ch in Charsets_1.CHARSETS) { + cs = Charsets_1.CHARSETS[ch]; + if (ch === '/') { + this.skipNextChar(); + } + } + else { + cs = Charsets_1.DEFAULT_CHARSET; + } + this._terminal.setgCharset(this._terminal.gcharset, cs); + this._terminal.gcharset = null; + this._state = ParserState.NORMAL; + break; + case ParserState.OSC: + if (ch === EscapeSequences_1.C0.ESC || ch === EscapeSequences_1.C0.BEL) { + if (ch === EscapeSequences_1.C0.ESC) + this._position++; + this._terminal.params.push(this._terminal.currentParam); + switch (this._terminal.params[0]) { + case 0: + case 1: + case 2: + if (this._terminal.params[1]) { + this._terminal.title = this._terminal.params[1]; + this._terminal.handleTitle(this._terminal.title); + } + break; + case 3: + break; + case 4: + case 5: + break; + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + break; + case 46: + break; + case 50: + break; + case 51: + break; + case 52: + break; + case 104: + case 105: + case 110: + case 111: + case 112: + case 113: + case 114: + case 115: + case 116: + case 117: + case 118: + break; + } + this._terminal.params = []; + this._terminal.currentParam = 0; + this._state = ParserState.NORMAL; + } + else { + if (!this._terminal.params.length) { + if (ch >= '0' && ch <= '9') { + this._terminal.currentParam = + this._terminal.currentParam * 10 + ch.charCodeAt(0) - 48; + } + else if (ch === ';') { + this._terminal.params.push(this._terminal.currentParam); + this._terminal.currentParam = ''; + } + } + else { + this._terminal.currentParam += ch; + } + } + break; + case ParserState.CSI_PARAM: + if (ch in csiParamStateHandler) { + csiParamStateHandler[ch](this); + break; + } + this.finalizeParam(); + this._state = ParserState.CSI; + case ParserState.CSI: + if (ch in csiStateHandler) { + if (this._terminal.debug) { + this._terminal.log("CSI " + (this._terminal.prefix ? this._terminal.prefix : '') + " " + (this._terminal.params ? this._terminal.params.join(';') : '') + " " + (this._terminal.postfix ? this._terminal.postfix : '') + " " + ch); + } + csiStateHandler[ch](this._inputHandler, this._terminal.params, this._terminal.prefix, this._terminal.postfix, this); + } + else { + this._terminal.error('Unknown CSI code: %s.', ch); + } + this._state = ParserState.NORMAL; + this._terminal.prefix = ''; + this._terminal.postfix = ''; + break; + case ParserState.DCS: + if (ch === EscapeSequences_1.C0.ESC || ch === EscapeSequences_1.C0.BEL) { + if (ch === EscapeSequences_1.C0.ESC) + this._position++; + var pt = void 0; + var valid = void 0; + switch (this._terminal.prefix) { + case '': + break; + case '$q': + pt = this._terminal.currentParam; + valid = false; + switch (pt) { + case '"q': + pt = '0"q'; + break; + case '"p': + pt = '61"p'; + break; + case 'r': + pt = '' + + (this._terminal.buffer.scrollTop + 1) + + ';' + + (this._terminal.buffer.scrollBottom + 1) + + 'r'; + break; + case 'm': + pt = '0m'; + break; + default: + this._terminal.error('Unknown DCS Pt: %s.', pt); + pt = ''; + break; + } + this._terminal.send(EscapeSequences_1.C0.ESC + 'P' + +valid + '$r' + pt + EscapeSequences_1.C0.ESC + '\\'); + break; + case '+p': + break; + case '+q': + pt = this._terminal.currentParam; + valid = false; + this._terminal.send(EscapeSequences_1.C0.ESC + 'P' + +valid + '+r' + pt + EscapeSequences_1.C0.ESC + '\\'); + break; + default: + this._terminal.error('Unknown DCS prefix: %s.', this._terminal.prefix); + break; + } + this._terminal.currentParam = 0; + this._terminal.prefix = ''; + this._state = ParserState.NORMAL; + } + else if (!this._terminal.currentParam) { + if (!this._terminal.prefix && ch !== '$' && ch !== '+') { + this._terminal.currentParam = ch; + } + else if (this._terminal.prefix.length === 2) { + this._terminal.currentParam = ch; + } + else { + this._terminal.prefix += ch; + } + } + else { + this._terminal.currentParam += ch; + } + break; + case ParserState.IGNORE: + if (ch === EscapeSequences_1.C0.ESC || ch === EscapeSequences_1.C0.BEL) { + if (ch === EscapeSequences_1.C0.ESC) + this._position++; + this._state = ParserState.NORMAL; + } + break; + } + } + if (this._terminal.buffer.x !== cursorStartX || this._terminal.buffer.y !== cursorStartY) { + this._terminal.emit('cursormove'); + } + return this._state; + }; + Parser.prototype.setState = function (state) { + this._state = state; + }; + Parser.prototype.setPrefix = function (prefix) { + this._terminal.prefix = prefix; + }; + Parser.prototype.setPostfix = function (postfix) { + this._terminal.postfix = postfix; + }; + Parser.prototype.setParam = function (param) { + this._terminal.currentParam = param; + }; + Parser.prototype.getParam = function () { + return this._terminal.currentParam; + }; + Parser.prototype.finalizeParam = function () { + this._terminal.params.push(this._terminal.currentParam); + this._terminal.currentParam = 0; + }; + Parser.prototype.skipNextChar = function () { + this._position++; + }; + return Parser; +}()); +exports.Parser = Parser; + + + +},{"./Charsets":4,"./EscapeSequences":6}],11:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var MouseHelper_1 = require("./utils/MouseHelper"); +var Browser = require("./utils/Browser"); +var EventEmitter_1 = require("./EventEmitter"); +var SelectionModel_1 = require("./SelectionModel"); +var Buffer_1 = require("./Buffer"); +var DRAG_SCROLL_MAX_THRESHOLD = 50; +var DRAG_SCROLL_MAX_SPEED = 15; +var DRAG_SCROLL_INTERVAL = 50; +var WORD_SEPARATORS = ' ()[]{}\'"'; +var NON_BREAKING_SPACE_CHAR = String.fromCharCode(160); +var ALL_NON_BREAKING_SPACE_REGEX = new RegExp(NON_BREAKING_SPACE_CHAR, 'g'); +var SelectionMode; +(function (SelectionMode) { + SelectionMode[SelectionMode["NORMAL"] = 0] = "NORMAL"; + SelectionMode[SelectionMode["WORD"] = 1] = "WORD"; + SelectionMode[SelectionMode["LINE"] = 2] = "LINE"; +})(SelectionMode || (SelectionMode = {})); +var SelectionManager = (function (_super) { + __extends(SelectionManager, _super); + function SelectionManager(_terminal, _buffer, _charMeasure) { + var _this = _super.call(this) || this; + _this._terminal = _terminal; + _this._buffer = _buffer; + _this._charMeasure = _charMeasure; + _this._enabled = true; + _this._initListeners(); + _this.enable(); + _this._model = new SelectionModel_1.SelectionModel(_terminal); + _this._activeSelectionMode = SelectionMode.NORMAL; + return _this; + } + SelectionManager.prototype._initListeners = function () { + var _this = this; + this._mouseMoveListener = function (event) { return _this._onMouseMove(event); }; + this._mouseUpListener = function (event) { return _this._onMouseUp(event); }; + this._buffer.lines.on('trim', function (amount) { return _this._onTrim(amount); }); + }; + SelectionManager.prototype.disable = function () { + this.clearSelection(); + this._enabled = false; + }; + SelectionManager.prototype.enable = function () { + this._enabled = true; + }; + SelectionManager.prototype.setBuffer = function (buffer) { + this._buffer = buffer; + this.clearSelection(); + }; + Object.defineProperty(SelectionManager.prototype, "selectionStart", { + get: function () { return this._model.finalSelectionStart; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SelectionManager.prototype, "selectionEnd", { + get: function () { return this._model.finalSelectionEnd; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SelectionManager.prototype, "hasSelection", { + get: function () { + var start = this._model.finalSelectionStart; + var end = this._model.finalSelectionEnd; + if (!start || !end) { + return false; + } + return start[0] !== end[0] || start[1] !== end[1]; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SelectionManager.prototype, "selectionText", { + get: function () { + var start = this._model.finalSelectionStart; + var end = this._model.finalSelectionEnd; + if (!start || !end) { + return ''; + } + var startRowEndCol = start[1] === end[1] ? end[0] : null; + var result = []; + result.push(this._buffer.translateBufferLineToString(start[1], true, start[0], startRowEndCol)); + for (var i = start[1] + 1; i <= end[1] - 1; i++) { + var bufferLine = this._buffer.lines.get(i); + var lineText = this._buffer.translateBufferLineToString(i, true); + if (bufferLine.isWrapped) { + result[result.length - 1] += lineText; + } + else { + result.push(lineText); + } + } + if (start[1] !== end[1]) { + var bufferLine = this._buffer.lines.get(end[1]); + var lineText = this._buffer.translateBufferLineToString(end[1], true, 0, end[0]); + if (bufferLine.isWrapped) { + result[result.length - 1] += lineText; + } + else { + result.push(lineText); + } + } + var formattedResult = result.map(function (line) { + return line.replace(ALL_NON_BREAKING_SPACE_REGEX, ' '); + }).join(Browser.isMSWindows ? '\r\n' : '\n'); + return formattedResult; + }, + enumerable: true, + configurable: true + }); + SelectionManager.prototype.clearSelection = function () { + this._model.clearSelection(); + this._removeMouseDownListeners(); + this.refresh(); + }; + SelectionManager.prototype.refresh = function (isNewSelection) { + var _this = this; + if (!this._refreshAnimationFrame) { + this._refreshAnimationFrame = window.requestAnimationFrame(function () { return _this._refresh(); }); + } + if (Browser.isLinux && isNewSelection) { + var selectionText = this.selectionText; + if (selectionText.length) { + this.emit('newselection', this.selectionText); + } + } + }; + SelectionManager.prototype._refresh = function () { + this._refreshAnimationFrame = null; + this.emit('refresh', { start: this._model.finalSelectionStart, end: this._model.finalSelectionEnd }); + }; + SelectionManager.prototype.selectAll = function () { + this._model.isSelectAllActive = true; + this.refresh(); + this._terminal.emit('selection'); + }; + SelectionManager.prototype._onTrim = function (amount) { + var needsRefresh = this._model.onTrim(amount); + if (needsRefresh) { + this.refresh(); + } + }; + SelectionManager.prototype._getMouseBufferCoords = function (event) { + var coords = this._terminal.mouseHelper.getCoords(event, this._terminal.element, this._charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows, true); + if (!coords) { + return null; + } + coords[0]--; + coords[1]--; + coords[1] += this._terminal.buffer.ydisp; + return coords; + }; + SelectionManager.prototype._getMouseEventScrollAmount = function (event) { + var offset = MouseHelper_1.MouseHelper.getCoordsRelativeToElement(event, this._terminal.element)[1]; + var terminalHeight = this._terminal.rows * Math.ceil(this._charMeasure.height * this._terminal.options.lineHeight); + if (offset >= 0 && offset <= terminalHeight) { + return 0; + } + if (offset > terminalHeight) { + offset -= terminalHeight; + } + offset = Math.min(Math.max(offset, -DRAG_SCROLL_MAX_THRESHOLD), DRAG_SCROLL_MAX_THRESHOLD); + offset /= DRAG_SCROLL_MAX_THRESHOLD; + return (offset / Math.abs(offset)) + Math.round(offset * (DRAG_SCROLL_MAX_SPEED - 1)); + }; + SelectionManager.prototype.shouldForceSelection = function (event) { + return Browser.isMac ? event.altKey : event.shiftKey; + }; + SelectionManager.prototype.onMouseDown = function (event) { + if (event.button === 2 && this.hasSelection) { + return; + } + if (event.button !== 0) { + return; + } + if (!this._enabled) { + if (!this.shouldForceSelection(event)) { + return; + } + event.stopPropagation(); + } + event.preventDefault(); + this._dragScrollAmount = 0; + if (this._enabled && event.shiftKey) { + this._onIncrementalClick(event); + } + else { + if (event.detail === 1) { + this._onSingleClick(event); + } + else if (event.detail === 2) { + this._onDoubleClick(event); + } + else if (event.detail === 3) { + this._onTripleClick(event); + } + } + this._addMouseDownListeners(); + this.refresh(true); + }; + SelectionManager.prototype._addMouseDownListeners = function () { + var _this = this; + this._terminal.element.ownerDocument.addEventListener('mousemove', this._mouseMoveListener); + this._terminal.element.ownerDocument.addEventListener('mouseup', this._mouseUpListener); + this._dragScrollIntervalTimer = setInterval(function () { return _this._dragScroll(); }, DRAG_SCROLL_INTERVAL); + }; + SelectionManager.prototype._removeMouseDownListeners = function () { + this._terminal.element.ownerDocument.removeEventListener('mousemove', this._mouseMoveListener); + this._terminal.element.ownerDocument.removeEventListener('mouseup', this._mouseUpListener); + clearInterval(this._dragScrollIntervalTimer); + this._dragScrollIntervalTimer = null; + }; + SelectionManager.prototype._onIncrementalClick = function (event) { + if (this._model.selectionStart) { + this._model.selectionEnd = this._getMouseBufferCoords(event); + } + }; + SelectionManager.prototype._onSingleClick = function (event) { + this._model.selectionStartLength = 0; + this._model.isSelectAllActive = false; + this._activeSelectionMode = SelectionMode.NORMAL; + this._model.selectionStart = this._getMouseBufferCoords(event); + if (!this._model.selectionStart) { + return; + } + this._model.selectionEnd = null; + var line = this._buffer.lines.get(this._model.selectionStart[1]); + if (!line) { + return; + } + if (line.length >= this._model.selectionStart[0]) { + return; + } + var char = line[this._model.selectionStart[0]]; + if (char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) { + this._model.selectionStart[0]++; + } + }; + SelectionManager.prototype._onDoubleClick = function (event) { + var coords = this._getMouseBufferCoords(event); + if (coords) { + this._activeSelectionMode = SelectionMode.WORD; + this._selectWordAt(coords); + } + }; + SelectionManager.prototype._onTripleClick = function (event) { + var coords = this._getMouseBufferCoords(event); + if (coords) { + this._activeSelectionMode = SelectionMode.LINE; + this._selectLineAt(coords[1]); + } + }; + SelectionManager.prototype._onMouseMove = function (event) { + event.stopImmediatePropagation(); + var previousSelectionEnd = this._model.selectionEnd ? [this._model.selectionEnd[0], this._model.selectionEnd[1]] : null; + this._model.selectionEnd = this._getMouseBufferCoords(event); + if (!this._model.selectionEnd) { + this.refresh(true); + return; + } + if (this._activeSelectionMode === SelectionMode.LINE) { + if (this._model.selectionEnd[1] < this._model.selectionStart[1]) { + this._model.selectionEnd[0] = 0; + } + else { + this._model.selectionEnd[0] = this._terminal.cols; + } + } + else if (this._activeSelectionMode === SelectionMode.WORD) { + this._selectToWordAt(this._model.selectionEnd); + } + this._dragScrollAmount = this._getMouseEventScrollAmount(event); + if (this._dragScrollAmount > 0) { + this._model.selectionEnd[0] = this._terminal.cols; + } + else if (this._dragScrollAmount < 0) { + this._model.selectionEnd[0] = 0; + } + if (this._model.selectionEnd[1] < this._buffer.lines.length) { + var char = this._buffer.lines.get(this._model.selectionEnd[1])[this._model.selectionEnd[0]]; + if (char && char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) { + this._model.selectionEnd[0]++; + } + } + if (!previousSelectionEnd || + previousSelectionEnd[0] !== this._model.selectionEnd[0] || + previousSelectionEnd[1] !== this._model.selectionEnd[1]) { + this.refresh(true); + } + }; + SelectionManager.prototype._dragScroll = function () { + if (this._dragScrollAmount) { + this._terminal.scrollLines(this._dragScrollAmount, false); + if (this._dragScrollAmount > 0) { + this._model.selectionEnd = [this._terminal.cols - 1, Math.min(this._terminal.buffer.ydisp + this._terminal.rows, this._terminal.buffer.lines.length - 1)]; + } + else { + this._model.selectionEnd = [0, this._terminal.buffer.ydisp]; + } + this.refresh(); + } + }; + SelectionManager.prototype._onMouseUp = function (event) { + this._removeMouseDownListeners(); + if (this.hasSelection) + this._terminal.emit('selection'); + }; + SelectionManager.prototype._convertViewportColToCharacterIndex = function (bufferLine, coords) { + var charIndex = coords[0]; + for (var i = 0; coords[0] >= i; i++) { + var char = bufferLine[i]; + if (char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) { + charIndex--; + } + else if (char[Buffer_1.CHAR_DATA_CHAR_INDEX].length > 1 && coords[0] !== i) { + charIndex += char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + } + } + return charIndex; + }; + SelectionManager.prototype.setSelection = function (col, row, length) { + this._model.clearSelection(); + this._removeMouseDownListeners(); + this._model.selectionStart = [col, row]; + this._model.selectionStartLength = length; + this.refresh(); + }; + SelectionManager.prototype._getWordAt = function (coords) { + var bufferLine = this._buffer.lines.get(coords[1]); + if (!bufferLine) { + return null; + } + var line = this._buffer.translateBufferLineToString(coords[1], false); + var startIndex = this._convertViewportColToCharacterIndex(bufferLine, coords); + var endIndex = startIndex; + var charOffset = coords[0] - startIndex; + var leftWideCharCount = 0; + var rightWideCharCount = 0; + var leftLongCharOffset = 0; + var rightLongCharOffset = 0; + if (line.charAt(startIndex) === ' ') { + while (startIndex > 0 && line.charAt(startIndex - 1) === ' ') { + startIndex--; + } + while (endIndex < line.length && line.charAt(endIndex + 1) === ' ') { + endIndex++; + } + } + else { + var startCol = coords[0]; + var endCol = coords[0]; + if (bufferLine[startCol][Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) { + leftWideCharCount++; + startCol--; + } + if (bufferLine[endCol][Buffer_1.CHAR_DATA_WIDTH_INDEX] === 2) { + rightWideCharCount++; + endCol++; + } + if (bufferLine[endCol][Buffer_1.CHAR_DATA_CHAR_INDEX].length > 1) { + rightLongCharOffset += bufferLine[endCol][Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + endIndex += bufferLine[endCol][Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + } + while (startCol > 0 && startIndex > 0 && !this._isCharWordSeparator(bufferLine[startCol - 1])) { + var char = bufferLine[startCol - 1]; + if (char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) { + leftWideCharCount++; + startCol--; + } + else if (char[Buffer_1.CHAR_DATA_CHAR_INDEX].length > 1) { + leftLongCharOffset += char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + startIndex -= char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + } + startIndex--; + startCol--; + } + while (endCol < bufferLine.length && endIndex + 1 < line.length && !this._isCharWordSeparator(bufferLine[endCol + 1])) { + var char = bufferLine[endCol + 1]; + if (char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 2) { + rightWideCharCount++; + endCol++; + } + else if (char[Buffer_1.CHAR_DATA_CHAR_INDEX].length > 1) { + rightLongCharOffset += char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + endIndex += char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + } + endIndex++; + endCol++; + } + } + endIndex++; + var start = startIndex + + charOffset + - leftWideCharCount + + leftLongCharOffset; + var length = Math.min(this._terminal.cols, endIndex + - startIndex + + leftWideCharCount + + rightWideCharCount + - leftLongCharOffset + - rightLongCharOffset); + return { start: start, length: length }; + }; + SelectionManager.prototype._selectWordAt = function (coords) { + var wordPosition = this._getWordAt(coords); + if (wordPosition) { + this._model.selectionStart = [wordPosition.start, coords[1]]; + this._model.selectionStartLength = wordPosition.length; + } + }; + SelectionManager.prototype._selectToWordAt = function (coords) { + var wordPosition = this._getWordAt(coords); + if (wordPosition) { + this._model.selectionEnd = [this._model.areSelectionValuesReversed() ? wordPosition.start : (wordPosition.start + wordPosition.length), coords[1]]; + } + }; + SelectionManager.prototype._isCharWordSeparator = function (charData) { + if (charData[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) { + return false; + } + return WORD_SEPARATORS.indexOf(charData[Buffer_1.CHAR_DATA_CHAR_INDEX]) >= 0; + }; + SelectionManager.prototype._selectLineAt = function (line) { + this._model.selectionStart = [0, line]; + this._model.selectionStartLength = this._terminal.cols; + }; + return SelectionManager; +}(EventEmitter_1.EventEmitter)); +exports.SelectionManager = SelectionManager; + + + +},{"./Buffer":1,"./EventEmitter":7,"./SelectionModel":12,"./utils/Browser":28,"./utils/MouseHelper":32}],12:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var SelectionModel = (function () { + function SelectionModel(_terminal) { + this._terminal = _terminal; + this.clearSelection(); + } + SelectionModel.prototype.clearSelection = function () { + this.selectionStart = null; + this.selectionEnd = null; + this.isSelectAllActive = false; + this.selectionStartLength = 0; + }; + Object.defineProperty(SelectionModel.prototype, "finalSelectionStart", { + get: function () { + if (this.isSelectAllActive) { + return [0, 0]; + } + if (!this.selectionEnd || !this.selectionStart) { + return this.selectionStart; + } + return this.areSelectionValuesReversed() ? this.selectionEnd : this.selectionStart; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SelectionModel.prototype, "finalSelectionEnd", { + get: function () { + if (this.isSelectAllActive) { + return [this._terminal.cols, this._terminal.buffer.ybase + this._terminal.rows - 1]; + } + if (!this.selectionStart) { + return null; + } + if (!this.selectionEnd || this.areSelectionValuesReversed()) { + return [this.selectionStart[0] + this.selectionStartLength, this.selectionStart[1]]; + } + if (this.selectionStartLength) { + if (this.selectionEnd[1] === this.selectionStart[1]) { + return [Math.max(this.selectionStart[0] + this.selectionStartLength, this.selectionEnd[0]), this.selectionEnd[1]]; + } + } + return this.selectionEnd; + }, + enumerable: true, + configurable: true + }); + SelectionModel.prototype.areSelectionValuesReversed = function () { + var start = this.selectionStart; + var end = this.selectionEnd; + if (!start || !end) { + return false; + } + return start[1] > end[1] || (start[1] === end[1] && start[0] > end[0]); + }; + SelectionModel.prototype.onTrim = function (amount) { + if (this.selectionStart) { + this.selectionStart[1] -= amount; + } + if (this.selectionEnd) { + this.selectionEnd[1] -= amount; + } + if (this.selectionEnd && this.selectionEnd[1] < 0) { + this.clearSelection(); + return true; + } + if (this.selectionStart && this.selectionStart[1] < 0) { + this.selectionStart[1] = 0; + } + return false; + }; + return SelectionModel; +}()); +exports.SelectionModel = SelectionModel; + + + +},{}],13:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var BufferSet_1 = require("./BufferSet"); +var Buffer_1 = require("./Buffer"); +var CompositionHelper_1 = require("./CompositionHelper"); +var EventEmitter_1 = require("./EventEmitter"); +var Viewport_1 = require("./Viewport"); +var Clipboard_1 = require("./handlers/Clipboard"); +var EscapeSequences_1 = require("./EscapeSequences"); +var InputHandler_1 = require("./InputHandler"); +var Parser_1 = require("./Parser"); +var Renderer_1 = require("./renderer/Renderer"); +var Linkifier_1 = require("./Linkifier"); +var SelectionManager_1 = require("./SelectionManager"); +var CharMeasure_1 = require("./utils/CharMeasure"); +var Browser = require("./utils/Browser"); +var MouseHelper_1 = require("./utils/MouseHelper"); +var Sounds_1 = require("./utils/Sounds"); +var ColorManager_1 = require("./renderer/ColorManager"); +var MouseZoneManager_1 = require("./input/MouseZoneManager"); +var CharAtlas_1 = require("./renderer/CharAtlas"); +var document = (typeof window !== 'undefined') ? window.document : null; +var WRITE_BUFFER_PAUSE_THRESHOLD = 5; +var WRITE_BATCH_SIZE = 300; +var DEFAULT_OPTIONS = { + cols: 80, + rows: 24, + convertEol: false, + termName: 'xterm', + cursorBlink: false, + cursorStyle: 'block', + bellSound: Sounds_1.BellSound, + bellStyle: 'none', + enableBold: true, + fontFamily: 'courier-new, courier, monospace', + fontSize: 15, + lineHeight: 1.0, + letterSpacing: 0, + scrollback: 1000, + screenKeys: false, + debug: false, + cancelEvents: false, + disableStdin: false, + useFlowControl: false, + allowTransparency: false, + tabStopWidth: 8, + theme: null +}; +var Terminal = (function (_super) { + __extends(Terminal, _super); + function Terminal(options) { + if (options === void 0) { options = {}; } + var _this = _super.call(this) || this; + _this.browser = Browser; + _this.options = options; + _this.setup(); + return _this; + } + Terminal.prototype.setup = function () { + var _this = this; + Object.keys(DEFAULT_OPTIONS).forEach(function (key) { + if (_this.options[key] == null) { + _this.options[key] = DEFAULT_OPTIONS[key]; + } + _this[key] = _this.options[key]; + }); + this.parent = document ? document.body : null; + this.cols = this.options.cols; + this.rows = this.options.rows; + if (this.options.handler) { + this.on('data', this.options.handler); + } + this.cursorState = 0; + this.cursorHidden = false; + this.sendDataQueue = ''; + this.customKeyEventHandler = null; + this.applicationKeypad = false; + this.applicationCursor = false; + this.originMode = false; + this.insertMode = false; + this.wraparoundMode = true; + this.bracketedPasteMode = false; + this.charset = null; + this.gcharset = null; + this.glevel = 0; + this.charsets = [null]; + this.readable = true; + this.writable = true; + this.defAttr = (0 << 18) | (257 << 9) | (256 << 0); + this.curAttr = (0 << 18) | (257 << 9) | (256 << 0); + this.params = []; + this.currentParam = 0; + this.prefix = ''; + this.postfix = ''; + this.writeBuffer = []; + this.writeInProgress = false; + this.xoffSentToCatchUp = false; + this.writeStopped = false; + this.surrogate_high = ''; + this.userScrolling = false; + this.inputHandler = new InputHandler_1.InputHandler(this); + this.parser = new Parser_1.Parser(this.inputHandler, this); + this.renderer = this.renderer || null; + this.selectionManager = this.selectionManager || null; + this.linkifier = this.linkifier || new Linkifier_1.Linkifier(this); + this._mouseZoneManager = this._mouseZoneManager || null; + this.buffers = new BufferSet_1.BufferSet(this); + this.buffer = this.buffers.active; + this.buffers.on('activate', function (buffer) { + _this.buffer = buffer; + }); + if (this.selectionManager) { + this.selectionManager.setBuffer(this.buffer); + } + }; + Terminal.prototype.eraseAttr = function () { + return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff); + }; + Terminal.prototype.focus = function () { + if (this.textarea) { + this.textarea.focus(); + } + }; + Object.defineProperty(Terminal.prototype, "isFocused", { + get: function () { + return document.activeElement === this.textarea; + }, + enumerable: true, + configurable: true + }); + Terminal.prototype.getOption = function (key) { + if (!(key in DEFAULT_OPTIONS)) { + throw new Error('No option with key "' + key + '"'); + } + if (typeof this.options[key] !== 'undefined') { + return this.options[key]; + } + return this[key]; + }; + Terminal.prototype.setOption = function (key, value) { + if (!(key in DEFAULT_OPTIONS)) { + throw new Error('No option with key "' + key + '"'); + } + switch (key) { + case 'bellStyle': + if (!value) { + value = 'none'; + } + break; + case 'cursorStyle': + if (!value) { + value = 'block'; + } + break; + case 'lineHeight': + if (value < 1) { + console.warn(key + " cannot be less than 1, value: " + value); + return; + } + case 'tabStopWidth': + if (value < 1) { + console.warn(key + " cannot be less than 1, value: " + value); + return; + } + break; + case 'theme': + if (this.renderer) { + this._setTheme(value); + return; + } + break; + case 'scrollback': + value = Math.min(value, Buffer_1.MAX_BUFFER_SIZE); + if (value < 0) { + console.warn(key + " cannot be less than 0, value: " + value); + return; + } + if (this.options[key] !== value) { + var newBufferLength = this.rows + value; + if (this.buffer.lines.length > newBufferLength) { + var amountToTrim = this.buffer.lines.length - newBufferLength; + var needsRefresh = (this.buffer.ydisp - amountToTrim < 0); + this.buffer.lines.trimStart(amountToTrim); + this.buffer.ybase = Math.max(this.buffer.ybase - amountToTrim, 0); + this.buffer.ydisp = Math.max(this.buffer.ydisp - amountToTrim, 0); + if (needsRefresh) { + this.refresh(0, this.rows - 1); + } + } + } + break; + } + this[key] = value; + this.options[key] = value; + switch (key) { + case 'fontFamily': + case 'fontSize': + this.renderer.clear(); + this.charMeasure.measure(this.options); + break; + case 'enableBold': + case 'letterSpacing': + case 'lineHeight': + this.renderer.clear(); + this.renderer.onResize(this.cols, this.rows, false); + this.refresh(0, this.rows - 1); + case 'scrollback': + this.buffers.resize(this.cols, this.rows); + this.viewport.syncScrollArea(); + break; + case 'tabStopWidth': + this.buffers.setupTabStops(); + break; + case 'bellSound': + case 'bellStyle': + this.syncBellSound(); + break; + } + if (this.renderer) { + this.renderer.onOptionsChanged(); + } + }; + Terminal.prototype._onTextAreaFocus = function () { + if (this.sendFocus) { + this.send(EscapeSequences_1.C0.ESC + '[I'); + } + this.element.classList.add('focus'); + this.showCursor(); + this.emit('focus'); + }; + ; + Terminal.prototype.blur = function () { + return this.textarea.blur(); + }; + Terminal.prototype._onTextAreaBlur = function () { + this.refresh(this.buffer.y, this.buffer.y); + if (this.sendFocus) { + this.send(EscapeSequences_1.C0.ESC + '[O'); + } + this.element.classList.remove('focus'); + this.emit('blur'); + }; + Terminal.prototype.initGlobal = function () { + var _this = this; + this.bindKeys(); + on(this.element, 'copy', function (event) { + if (!_this.hasSelection()) { + return; + } + Clipboard_1.copyHandler(event, _this, _this.selectionManager); + }); + var pasteHandlerWrapper = function (event) { return Clipboard_1.pasteHandler(event, _this); }; + on(this.textarea, 'paste', pasteHandlerWrapper); + on(this.element, 'paste', pasteHandlerWrapper); + if (Browser.isFirefox) { + on(this.element, 'mousedown', function (event) { + if (event.button === 2) { + Clipboard_1.rightClickHandler(event, _this.textarea, _this.selectionManager); + } + }); + } + else { + on(this.element, 'contextmenu', function (event) { + Clipboard_1.rightClickHandler(event, _this.textarea, _this.selectionManager); + }); + } + if (Browser.isLinux) { + on(this.element, 'auxclick', function (event) { + if (event.button === 1) { + Clipboard_1.moveTextAreaUnderMouseCursor(event, _this.textarea); + } + }); + } + }; + Terminal.prototype.bindKeys = function () { + var _this = this; + var self = this; + on(this.element, 'keydown', function (ev) { + if (document.activeElement !== this) { + return; + } + self._keyDown(ev); + }, true); + on(this.element, 'keypress', function (ev) { + if (document.activeElement !== this) { + return; + } + self._keyPress(ev); + }, true); + on(this.element, 'keyup', function (ev) { + if (!wasMondifierKeyOnlyEvent(ev)) { + _this.focus(); + } + }, true); + on(this.textarea, 'keydown', function (ev) { + _this._keyDown(ev); + }, true); + on(this.textarea, 'keypress', function (ev) { + _this._keyPress(ev); + _this.textarea.value = ''; + }, true); + on(this.textarea, 'compositionstart', function () { return _this.compositionHelper.compositionstart(); }); + on(this.textarea, 'compositionupdate', function (e) { return _this.compositionHelper.compositionupdate(e); }); + on(this.textarea, 'compositionend', function () { return _this.compositionHelper.compositionend(); }); + this.on('refresh', function () { return _this.compositionHelper.updateCompositionElements(); }); + this.on('refresh', function (data) { return _this.queueLinkification(data.start, data.end); }); + }; + Terminal.prototype.open = function (parent) { + var _this = this; + var i = 0; + var div; + this.parent = parent || this.parent; + if (!this.parent) { + throw new Error('Terminal requires a parent element.'); + } + this.context = this.parent.ownerDocument.defaultView; + this.document = this.parent.ownerDocument; + this.body = this.document.body; + CharAtlas_1.initialize(this.document, this.options.allowTransparency); + this.element = this.document.createElement('div'); + this.element.classList.add('terminal'); + this.element.classList.add('xterm'); + this.element.setAttribute('tabindex', '0'); + this.parent.appendChild(this.element); + var fragment = document.createDocumentFragment(); + this.viewportElement = document.createElement('div'); + this.viewportElement.classList.add('xterm-viewport'); + fragment.appendChild(this.viewportElement); + this.viewportScrollArea = document.createElement('div'); + this.viewportScrollArea.classList.add('xterm-scroll-area'); + this.viewportElement.appendChild(this.viewportScrollArea); + this._mouseZoneManager = new MouseZoneManager_1.MouseZoneManager(this); + this.on('scroll', function () { return _this._mouseZoneManager.clearAll(); }); + this.linkifier.attachToDom(this._mouseZoneManager); + this.helperContainer = document.createElement('div'); + this.helperContainer.classList.add('xterm-helpers'); + fragment.appendChild(this.helperContainer); + this.textarea = document.createElement('textarea'); + this.textarea.classList.add('xterm-helper-textarea'); + this.textarea.setAttribute('autocorrect', 'off'); + this.textarea.setAttribute('autocapitalize', 'off'); + this.textarea.setAttribute('spellcheck', 'false'); + this.textarea.tabIndex = 0; + this.textarea.addEventListener('focus', function () { return _this._onTextAreaFocus(); }); + this.textarea.addEventListener('blur', function () { return _this._onTextAreaBlur(); }); + this.helperContainer.appendChild(this.textarea); + this.compositionView = document.createElement('div'); + this.compositionView.classList.add('composition-view'); + this.compositionHelper = new CompositionHelper_1.CompositionHelper(this.textarea, this.compositionView, this); + this.helperContainer.appendChild(this.compositionView); + this.charSizeStyleElement = document.createElement('style'); + this.helperContainer.appendChild(this.charSizeStyleElement); + this.charMeasure = new CharMeasure_1.CharMeasure(document, this.helperContainer); + this.syncBellSound(); + this.element.appendChild(fragment); + this.renderer = new Renderer_1.Renderer(this, this.options.theme); + this.options.theme = null; + this.viewport = new Viewport_1.Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure); + this.viewport.onThemeChanged(this.renderer.colorManager.colors); + this.on('cursormove', function () { return _this.renderer.onCursorMove(); }); + this.on('resize', function () { return _this.renderer.onResize(_this.cols, _this.rows, false); }); + this.on('blur', function () { return _this.renderer.onBlur(); }); + this.on('focus', function () { return _this.renderer.onFocus(); }); + this.charMeasure.on('charsizechanged', function () { return _this.renderer.onResize(_this.cols, _this.rows, true); }); + this.renderer.on('resize', function (dimensions) { return _this.viewport.syncScrollArea(); }); + this.selectionManager = new SelectionManager_1.SelectionManager(this, this.buffer, this.charMeasure); + this.element.addEventListener('mousedown', function (e) { return _this.selectionManager.onMouseDown(e); }); + this.selectionManager.on('refresh', function (data) { return _this.renderer.onSelectionChanged(data.start, data.end); }); + this.selectionManager.on('newselection', function (text) { + _this.textarea.value = text; + _this.textarea.focus(); + _this.textarea.select(); + }); + this.on('scroll', function () { + _this.viewport.syncScrollArea(); + _this.selectionManager.refresh(); + }); + this.viewportElement.addEventListener('scroll', function () { return _this.selectionManager.refresh(); }); + this.mouseHelper = new MouseHelper_1.MouseHelper(this.renderer); + this.charMeasure.measure(this.options); + this.refresh(0, this.rows - 1); + this.initGlobal(); + this.bindMouse(); + }; + Terminal.prototype._setTheme = function (theme) { + var colors = this.renderer.setTheme(theme); + if (this.viewport) { + this.viewport.onThemeChanged(colors); + } + }; + Terminal.applyAddon = function (addon) { + addon.apply(Terminal); + }; + Terminal.prototype.bindMouse = function () { + var _this = this; + var el = this.element; + var self = this; + var pressed = 32; + function sendButton(ev) { + var button; + var pos; + button = getButton(ev); + pos = self.mouseHelper.getRawByteCoords(ev, self.element, self.charMeasure, self.options.lineHeight, self.cols, self.rows); + if (!pos) + return; + sendEvent(button, pos); + switch (ev.overrideType || ev.type) { + case 'mousedown': + pressed = button; + break; + case 'mouseup': + pressed = 32; + break; + case 'wheel': + break; + } + } + function sendMove(ev) { + var button = pressed; + var pos = self.mouseHelper.getRawByteCoords(ev, self.element, self.charMeasure, self.options.lineHeight, self.cols, self.rows); + if (!pos) + return; + button += 32; + sendEvent(button, pos); + } + function encode(data, ch) { + if (!self.utfMouse) { + if (ch === 255) { + data.push(0); + return; + } + if (ch > 127) + ch = 127; + data.push(ch); + } + else { + if (ch === 2047) { + data.push(0); + return; + } + if (ch < 127) { + data.push(ch); + } + else { + if (ch > 2047) + ch = 2047; + data.push(0xC0 | (ch >> 6)); + data.push(0x80 | (ch & 0x3F)); + } + } + } + function sendEvent(button, pos) { + if (self.vt300Mouse) { + button &= 3; + pos.x -= 32; + pos.y -= 32; + var data_1 = EscapeSequences_1.C0.ESC + '[24'; + if (button === 0) + data_1 += '1'; + else if (button === 1) + data_1 += '3'; + else if (button === 2) + data_1 += '5'; + else if (button === 3) + return; + else + data_1 += '0'; + data_1 += '~[' + pos.x + ',' + pos.y + ']\r'; + self.send(data_1); + return; + } + if (self.decLocator) { + button &= 3; + pos.x -= 32; + pos.y -= 32; + if (button === 0) + button = 2; + else if (button === 1) + button = 4; + else if (button === 2) + button = 6; + else if (button === 3) + button = 3; + self.send(EscapeSequences_1.C0.ESC + '[' + + button + + ';' + + (button === 3 ? 4 : 0) + + ';' + + pos.y + + ';' + + pos.x + + ';' + + pos.page || 0 + + '&w'); + return; + } + if (self.urxvtMouse) { + pos.x -= 32; + pos.y -= 32; + pos.x++; + pos.y++; + self.send(EscapeSequences_1.C0.ESC + '[' + button + ';' + pos.x + ';' + pos.y + 'M'); + return; + } + if (self.sgrMouse) { + pos.x -= 32; + pos.y -= 32; + self.send(EscapeSequences_1.C0.ESC + '[<' + + (((button & 3) === 3 ? button & ~3 : button) - 32) + + ';' + + pos.x + + ';' + + pos.y + + ((button & 3) === 3 ? 'm' : 'M')); + return; + } + var data = []; + encode(data, button); + encode(data, pos.x); + encode(data, pos.y); + self.send(EscapeSequences_1.C0.ESC + '[M' + String.fromCharCode.apply(String, data)); + } + function getButton(ev) { + var button; + var shift; + var meta; + var ctrl; + var mod; + switch (ev.overrideType || ev.type) { + case 'mousedown': + button = ev.button != null + ? +ev.button + : ev.which != null + ? ev.which - 1 + : null; + if (Browser.isMSIE) { + button = button === 1 ? 0 : button === 4 ? 1 : button; + } + break; + case 'mouseup': + button = 3; + break; + case 'DOMMouseScroll': + button = ev.detail < 0 + ? 64 + : 65; + break; + case 'wheel': + button = ev.wheelDeltaY > 0 + ? 64 + : 65; + break; + } + shift = ev.shiftKey ? 4 : 0; + meta = ev.metaKey ? 8 : 0; + ctrl = ev.ctrlKey ? 16 : 0; + mod = shift | meta | ctrl; + if (self.vt200Mouse) { + mod &= ctrl; + } + else if (!self.normalMouse) { + mod = 0; + } + button = (32 + (mod << 2)) + button; + return button; + } + on(el, 'mousedown', function (ev) { + ev.preventDefault(); + _this.focus(); + if (!_this.mouseEvents || _this.selectionManager.shouldForceSelection(ev)) { + return; + } + sendButton(ev); + if (_this.vt200Mouse) { + ev.overrideType = 'mouseup'; + sendButton(ev); + return _this.cancel(ev); + } + if (_this.normalMouse) + on(_this.document, 'mousemove', sendMove); + if (!_this.x10Mouse) { + var handler_1 = function (ev) { + sendButton(ev); + if (_this.normalMouse) + off(_this.document, 'mousemove', sendMove); + off(_this.document, 'mouseup', handler_1); + return _this.cancel(ev); + }; + on(_this.document, 'mouseup', handler_1); + } + return _this.cancel(ev); + }); + on(el, 'wheel', function (ev) { + if (!_this.mouseEvents) + return; + if (_this.x10Mouse || _this.vt300Mouse || _this.decLocator) + return; + sendButton(ev); + ev.preventDefault(); + }); + on(el, 'wheel', function (ev) { + if (_this.mouseEvents) + return; + _this.viewport.onWheel(ev); + return _this.cancel(ev); + }); + on(el, 'touchstart', function (ev) { + if (_this.mouseEvents) + return; + _this.viewport.onTouchStart(ev); + return _this.cancel(ev); + }); + on(el, 'touchmove', function (ev) { + if (_this.mouseEvents) + return; + _this.viewport.onTouchMove(ev); + return _this.cancel(ev); + }); + }; + Terminal.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.readable = false; + this.writable = false; + this.handler = function () { }; + this.write = function () { }; + if (this.element && this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + } + }; + Terminal.prototype.refresh = function (start, end) { + if (this.renderer) { + this.renderer.queueRefresh(start, end); + } + }; + Terminal.prototype.queueLinkification = function (start, end) { + if (this.linkifier) { + this.linkifier.linkifyRows(start, end); + } + }; + Terminal.prototype.showCursor = function () { + if (!this.cursorState) { + this.cursorState = 1; + this.refresh(this.buffer.y, this.buffer.y); + } + }; + Terminal.prototype.scroll = function (isWrapped) { + var newLine = this.blankLine(undefined, isWrapped); + var topRow = this.buffer.ybase + this.buffer.scrollTop; + var bottomRow = this.buffer.ybase + this.buffer.scrollBottom; + if (this.buffer.scrollTop === 0) { + var willBufferBeTrimmed = this.buffer.lines.length === this.buffer.lines.maxLength; + if (bottomRow === this.buffer.lines.length - 1) { + this.buffer.lines.push(newLine); + } + else { + this.buffer.lines.splice(bottomRow + 1, 0, newLine); + } + if (!willBufferBeTrimmed) { + this.buffer.ybase++; + if (!this.userScrolling) { + this.buffer.ydisp++; + } + } + else { + if (this.userScrolling) { + this.buffer.ydisp = Math.max(this.buffer.ydisp - 1, 0); + } + } + } + else { + var scrollRegionHeight = bottomRow - topRow + 1; + this.buffer.lines.shiftElements(topRow + 1, scrollRegionHeight - 1, -1); + this.buffer.lines.set(bottomRow, newLine); + } + if (!this.userScrolling) { + this.buffer.ydisp = this.buffer.ybase; + } + this.updateRange(this.buffer.scrollTop); + this.updateRange(this.buffer.scrollBottom); + this.emit('scroll', this.buffer.ydisp); + }; + Terminal.prototype.scrollLines = function (disp, suppressScrollEvent) { + if (disp < 0) { + if (this.buffer.ydisp === 0) { + return; + } + this.userScrolling = true; + } + else if (disp + this.buffer.ydisp >= this.buffer.ybase) { + this.userScrolling = false; + } + var oldYdisp = this.buffer.ydisp; + this.buffer.ydisp = Math.max(Math.min(this.buffer.ydisp + disp, this.buffer.ybase), 0); + if (oldYdisp === this.buffer.ydisp) { + return; + } + if (!suppressScrollEvent) { + this.emit('scroll', this.buffer.ydisp); + } + this.refresh(0, this.rows - 1); + }; + Terminal.prototype.scrollPages = function (pageCount) { + this.scrollLines(pageCount * (this.rows - 1)); + }; + Terminal.prototype.scrollToTop = function () { + this.scrollLines(-this.buffer.ydisp); + }; + Terminal.prototype.scrollToBottom = function () { + this.scrollLines(this.buffer.ybase - this.buffer.ydisp); + }; + Terminal.prototype.write = function (data) { + var _this = this; + this.writeBuffer.push(data); + if (this.options.useFlowControl && !this.xoffSentToCatchUp && this.writeBuffer.length >= WRITE_BUFFER_PAUSE_THRESHOLD) { + this.send(EscapeSequences_1.C0.DC3); + this.xoffSentToCatchUp = true; + } + if (!this.writeInProgress && this.writeBuffer.length > 0) { + this.writeInProgress = true; + setTimeout(function () { + _this.innerWrite(); + }); + } + }; + Terminal.prototype.innerWrite = function () { + var _this = this; + var writeBatch = this.writeBuffer.splice(0, WRITE_BATCH_SIZE); + while (writeBatch.length > 0) { + var data = writeBatch.shift(); + if (this.xoffSentToCatchUp && writeBatch.length === 0 && this.writeBuffer.length === 0) { + this.send(EscapeSequences_1.C0.DC1); + this.xoffSentToCatchUp = false; + } + this.refreshStart = this.buffer.y; + this.refreshEnd = this.buffer.y; + var state = this.parser.parse(data); + this.parser.setState(state); + this.updateRange(this.buffer.y); + this.refresh(this.refreshStart, this.refreshEnd); + } + if (this.writeBuffer.length > 0) { + setTimeout(function () { return _this.innerWrite(); }, 0); + } + else { + this.writeInProgress = false; + } + }; + Terminal.prototype.writeln = function (data) { + this.write(data + '\r\n'); + }; + Terminal.prototype.attachCustomKeyEventHandler = function (customKeyEventHandler) { + this.customKeyEventHandler = customKeyEventHandler; + }; + Terminal.prototype.setHypertextLinkHandler = function (handler) { + if (!this.linkifier) { + throw new Error('Cannot attach a hypertext link handler before Terminal.open is called'); + } + this.linkifier.setHypertextLinkHandler(handler); + this.refresh(0, this.rows - 1); + }; + Terminal.prototype.setHypertextValidationCallback = function (callback) { + if (!this.linkifier) { + throw new Error('Cannot attach a hypertext validation callback before Terminal.open is called'); + } + this.linkifier.setHypertextValidationCallback(callback); + this.refresh(0, this.rows - 1); + }; + Terminal.prototype.registerLinkMatcher = function (regex, handler, options) { + if (this.linkifier) { + var matcherId = this.linkifier.registerLinkMatcher(regex, handler, options); + this.refresh(0, this.rows - 1); + return matcherId; + } + return 0; + }; + Terminal.prototype.deregisterLinkMatcher = function (matcherId) { + if (this.linkifier) { + if (this.linkifier.deregisterLinkMatcher(matcherId)) { + this.refresh(0, this.rows - 1); + } + } + }; + Terminal.prototype.hasSelection = function () { + return this.selectionManager ? this.selectionManager.hasSelection : false; + }; + Terminal.prototype.getSelection = function () { + return this.selectionManager ? this.selectionManager.selectionText : ''; + }; + Terminal.prototype.clearSelection = function () { + if (this.selectionManager) { + this.selectionManager.clearSelection(); + } + }; + Terminal.prototype.selectAll = function () { + if (this.selectionManager) { + this.selectionManager.selectAll(); + } + }; + Terminal.prototype._keyDown = function (ev) { + if (this.customKeyEventHandler && this.customKeyEventHandler(ev) === false) { + return false; + } + if (!this.compositionHelper.keydown(ev)) { + if (this.buffer.ybase !== this.buffer.ydisp) { + this.scrollToBottom(); + } + return false; + } + var result = this._evaluateKeyEscapeSequence(ev); + if (result.key === EscapeSequences_1.C0.DC3) { + this.writeStopped = true; + } + else if (result.key === EscapeSequences_1.C0.DC1) { + this.writeStopped = false; + } + if (result.scrollLines) { + this.scrollLines(result.scrollLines); + return this.cancel(ev, true); + } + if (isThirdLevelShift(this.browser, ev)) { + return true; + } + if (result.cancel) { + this.cancel(ev, true); + } + if (!result.key) { + return true; + } + this.emit('keydown', ev); + this.emit('key', result.key, ev); + this.showCursor(); + this.handler(result.key); + return this.cancel(ev, true); + }; + Terminal.prototype._evaluateKeyEscapeSequence = function (ev) { + var result = { + cancel: false, + key: undefined, + scrollLines: undefined + }; + var modifiers = (ev.shiftKey ? 1 : 0) | (ev.altKey ? 2 : 0) | (ev.ctrlKey ? 4 : 0) | (ev.metaKey ? 8 : 0); + switch (ev.keyCode) { + case 0: + if (ev.key === 'UIKeyInputUpArrow') { + if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OA'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[A'; + } + } + else if (ev.key === 'UIKeyInputLeftArrow') { + if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OD'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[D'; + } + } + else if (ev.key === 'UIKeyInputRightArrow') { + if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OC'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[C'; + } + } + else if (ev.key === 'UIKeyInputDownArrow') { + if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OB'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[B'; + } + } + break; + case 8: + if (ev.shiftKey) { + result.key = EscapeSequences_1.C0.BS; + break; + } + else if (ev.altKey) { + result.key = EscapeSequences_1.C0.ESC + EscapeSequences_1.C0.DEL; + break; + } + result.key = EscapeSequences_1.C0.DEL; + break; + case 9: + if (ev.shiftKey) { + result.key = EscapeSequences_1.C0.ESC + '[Z'; + break; + } + result.key = EscapeSequences_1.C0.HT; + result.cancel = true; + break; + case 13: + result.key = EscapeSequences_1.C0.CR; + result.cancel = true; + break; + case 27: + result.key = EscapeSequences_1.C0.ESC; + result.cancel = true; + break; + case 37: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'D'; + if (result.key === EscapeSequences_1.C0.ESC + '[1;3D') { + result.key = (this.browser.isMac) ? EscapeSequences_1.C0.ESC + 'b' : EscapeSequences_1.C0.ESC + '[1;5D'; + } + } + else if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OD'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[D'; + } + break; + case 39: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'C'; + if (result.key === EscapeSequences_1.C0.ESC + '[1;3C') { + result.key = (this.browser.isMac) ? EscapeSequences_1.C0.ESC + 'f' : EscapeSequences_1.C0.ESC + '[1;5C'; + } + } + else if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OC'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[C'; + } + break; + case 38: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'A'; + if (result.key === EscapeSequences_1.C0.ESC + '[1;3A') { + result.key = EscapeSequences_1.C0.ESC + '[1;5A'; + } + } + else if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OA'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[A'; + } + break; + case 40: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'B'; + if (result.key === EscapeSequences_1.C0.ESC + '[1;3B') { + result.key = EscapeSequences_1.C0.ESC + '[1;5B'; + } + } + else if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OB'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[B'; + } + break; + case 45: + if (!ev.shiftKey && !ev.ctrlKey) { + result.key = EscapeSequences_1.C0.ESC + '[2~'; + } + break; + case 46: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[3;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[3~'; + } + break; + case 36: + if (modifiers) + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'H'; + else if (this.applicationCursor) + result.key = EscapeSequences_1.C0.ESC + 'OH'; + else + result.key = EscapeSequences_1.C0.ESC + '[H'; + break; + case 35: + if (modifiers) + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'F'; + else if (this.applicationCursor) + result.key = EscapeSequences_1.C0.ESC + 'OF'; + else + result.key = EscapeSequences_1.C0.ESC + '[F'; + break; + case 33: + if (ev.shiftKey) { + result.scrollLines = -(this.rows - 1); + } + else { + result.key = EscapeSequences_1.C0.ESC + '[5~'; + } + break; + case 34: + if (ev.shiftKey) { + result.scrollLines = this.rows - 1; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[6~'; + } + break; + case 112: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'P'; + } + else { + result.key = EscapeSequences_1.C0.ESC + 'OP'; + } + break; + case 113: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'Q'; + } + else { + result.key = EscapeSequences_1.C0.ESC + 'OQ'; + } + break; + case 114: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'R'; + } + else { + result.key = EscapeSequences_1.C0.ESC + 'OR'; + } + break; + case 115: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'S'; + } + else { + result.key = EscapeSequences_1.C0.ESC + 'OS'; + } + break; + case 116: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[15;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[15~'; + } + break; + case 117: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[17;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[17~'; + } + break; + case 118: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[18;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[18~'; + } + break; + case 119: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[19;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[19~'; + } + break; + case 120: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[20;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[20~'; + } + break; + case 121: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[21;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[21~'; + } + break; + case 122: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[23;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[23~'; + } + break; + case 123: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[24;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[24~'; + } + break; + default: + if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { + if (ev.keyCode >= 65 && ev.keyCode <= 90) { + result.key = String.fromCharCode(ev.keyCode - 64); + } + else if (ev.keyCode === 32) { + result.key = String.fromCharCode(0); + } + else if (ev.keyCode >= 51 && ev.keyCode <= 55) { + result.key = String.fromCharCode(ev.keyCode - 51 + 27); + } + else if (ev.keyCode === 56) { + result.key = String.fromCharCode(127); + } + else if (ev.keyCode === 219) { + result.key = String.fromCharCode(27); + } + else if (ev.keyCode === 220) { + result.key = String.fromCharCode(28); + } + else if (ev.keyCode === 221) { + result.key = String.fromCharCode(29); + } + } + else if (!this.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) { + if (ev.keyCode >= 65 && ev.keyCode <= 90) { + result.key = EscapeSequences_1.C0.ESC + String.fromCharCode(ev.keyCode + 32); + } + else if (ev.keyCode === 192) { + result.key = EscapeSequences_1.C0.ESC + '`'; + } + else if (ev.keyCode >= 48 && ev.keyCode <= 57) { + result.key = EscapeSequences_1.C0.ESC + (ev.keyCode - 48); + } + } + else if (this.browser.isMac && !ev.altKey && !ev.ctrlKey && ev.metaKey) { + if (ev.keyCode === 65) { + this.selectAll(); + } + } + break; + } + return result; + }; + Terminal.prototype.setgLevel = function (g) { + this.glevel = g; + this.charset = this.charsets[g]; + }; + Terminal.prototype.setgCharset = function (g, charset) { + this.charsets[g] = charset; + if (this.glevel === g) { + this.charset = charset; + } + }; + Terminal.prototype._keyPress = function (ev) { + var key; + if (this.customKeyEventHandler && this.customKeyEventHandler(ev) === false) { + return false; + } + this.cancel(ev); + if (ev.charCode) { + key = ev.charCode; + } + else if (ev.which == null) { + key = ev.keyCode; + } + else if (ev.which !== 0 && ev.charCode !== 0) { + key = ev.which; + } + else { + return false; + } + if (!key || ((ev.altKey || ev.ctrlKey || ev.metaKey) && !isThirdLevelShift(this.browser, ev))) { + return false; + } + key = String.fromCharCode(key); + this.emit('keypress', key, ev); + this.emit('key', key, ev); + this.showCursor(); + this.handler(key); + return true; + }; + Terminal.prototype.send = function (data) { + var _this = this; + if (!this.sendDataQueue) { + setTimeout(function () { + _this.handler(_this.sendDataQueue); + _this.sendDataQueue = ''; + }, 1); + } + this.sendDataQueue += data; + }; + Terminal.prototype.bell = function () { + var _this = this; + this.emit('bell'); + if (this.soundBell()) + this.bellAudioElement.play(); + if (this.visualBell()) { + this.element.classList.add('visual-bell-active'); + clearTimeout(this.visualBellTimer); + this.visualBellTimer = window.setTimeout(function () { + _this.element.classList.remove('visual-bell-active'); + }, 200); + } + }; + Terminal.prototype.log = function (text, data) { + if (!this.options.debug) + return; + if (!this.context.console || !this.context.console.log) + return; + this.context.console.log(text, data); + }; + Terminal.prototype.error = function (text, data) { + if (!this.options.debug) + return; + if (!this.context.console || !this.context.console.error) + return; + this.context.console.error(text, data); + }; + Terminal.prototype.resize = function (x, y) { + if (isNaN(x) || isNaN(y)) { + return; + } + if (x === this.cols && y === this.rows) { + if (!this.charMeasure.width || !this.charMeasure.height) { + this.charMeasure.measure(this.options); + } + return; + } + if (x < 1) + x = 1; + if (y < 1) + y = 1; + this.buffers.resize(x, y); + this.cols = x; + this.rows = y; + this.buffers.setupTabStops(this.cols); + this.charMeasure.measure(this.options); + this.refresh(0, this.rows - 1); + this.emit('resize', { cols: x, rows: y }); + }; + Terminal.prototype.updateRange = function (y) { + if (y < this.refreshStart) + this.refreshStart = y; + if (y > this.refreshEnd) + this.refreshEnd = y; + }; + Terminal.prototype.maxRange = function () { + this.refreshStart = 0; + this.refreshEnd = this.rows - 1; + }; + Terminal.prototype.eraseRight = function (x, y) { + var line = this.buffer.lines.get(this.buffer.ybase + y); + if (!line) { + return; + } + var ch = [this.eraseAttr(), ' ', 1, 32]; + for (; x < this.cols; x++) { + line[x] = ch; + } + this.updateRange(y); + }; + Terminal.prototype.eraseLeft = function (x, y) { + var line = this.buffer.lines.get(this.buffer.ybase + y); + if (!line) { + return; + } + var ch = [this.eraseAttr(), ' ', 1, 32]; + x++; + while (x--) { + line[x] = ch; + } + this.updateRange(y); + }; + Terminal.prototype.clear = function () { + if (this.buffer.ybase === 0 && this.buffer.y === 0) { + return; + } + this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y)); + this.buffer.lines.length = 1; + this.buffer.ydisp = 0; + this.buffer.ybase = 0; + this.buffer.y = 0; + for (var i = 1; i < this.rows; i++) { + this.buffer.lines.push(this.blankLine()); + } + this.refresh(0, this.rows - 1); + this.emit('scroll', this.buffer.ydisp); + }; + Terminal.prototype.eraseLine = function (y) { + this.eraseRight(0, y); + }; + Terminal.prototype.blankLine = function (cur, isWrapped, cols) { + var attr = cur ? this.eraseAttr() : this.defAttr; + var ch = [attr, ' ', 1, 32]; + var line = []; + if (isWrapped) { + line.isWrapped = isWrapped; + } + cols = cols || this.cols; + for (var i = 0; i < cols; i++) { + line[i] = ch; + } + return line; + }; + Terminal.prototype.ch = function (cur) { + if (cur) { + return [this.eraseAttr(), ' ', 1, 32]; + } + return [this.defAttr, ' ', 1, 32]; + }; + Terminal.prototype.is = function (term) { + return (this.options.termName + '').indexOf(term) === 0; + }; + Terminal.prototype.handler = function (data) { + if (this.options.disableStdin) { + return; + } + if (this.selectionManager && this.selectionManager.hasSelection) { + this.selectionManager.clearSelection(); + } + if (this.buffer.ybase !== this.buffer.ydisp) { + this.scrollToBottom(); + } + this.emit('data', data); + }; + Terminal.prototype.handleTitle = function (title) { + this.emit('title', title); + }; + Terminal.prototype.index = function () { + this.buffer.y++; + if (this.buffer.y > this.buffer.scrollBottom) { + this.buffer.y--; + this.scroll(); + } + if (this.buffer.x >= this.cols) { + this.buffer.x--; + } + }; + Terminal.prototype.reverseIndex = function () { + if (this.buffer.y === this.buffer.scrollTop) { + var scrollRegionHeight = this.buffer.scrollBottom - this.buffer.scrollTop; + this.buffer.lines.shiftElements(this.buffer.y + this.buffer.ybase, scrollRegionHeight, 1); + this.buffer.lines.set(this.buffer.y + this.buffer.ybase, this.blankLine(true)); + this.updateRange(this.buffer.scrollTop); + this.updateRange(this.buffer.scrollBottom); + } + else { + this.buffer.y--; + } + }; + Terminal.prototype.reset = function () { + this.options.rows = this.rows; + this.options.cols = this.cols; + var customKeyEventHandler = this.customKeyEventHandler; + var inputHandler = this.inputHandler; + var buffers = this.buffers; + this.setup(); + this.customKeyEventHandler = customKeyEventHandler; + this.inputHandler = inputHandler; + this.buffers = buffers; + this.refresh(0, this.rows - 1); + this.viewport.syncScrollArea(); + }; + Terminal.prototype.tabSet = function () { + this.buffer.tabs[this.buffer.x] = true; + }; + Terminal.prototype.cancel = function (ev, force) { + if (!this.options.cancelEvents && !force) { + return; + } + ev.preventDefault(); + ev.stopPropagation(); + return false; + }; + Terminal.prototype.matchColor = function (r1, g1, b1) { + return matchColor_(r1, g1, b1); + }; + Terminal.prototype.visualBell = function () { + return this.options.bellStyle === 'visual' || + this.options.bellStyle === 'both'; + }; + Terminal.prototype.soundBell = function () { + return this.options.bellStyle === 'sound' || + this.options.bellStyle === 'both'; + }; + Terminal.prototype.syncBellSound = function () { + if (!this.element) { + return; + } + if (this.soundBell() && this.bellAudioElement) { + this.bellAudioElement.setAttribute('src', this.options.bellSound); + } + else if (this.soundBell()) { + this.bellAudioElement = document.createElement('audio'); + this.bellAudioElement.setAttribute('preload', 'auto'); + this.bellAudioElement.setAttribute('src', this.options.bellSound); + this.helperContainer.appendChild(this.bellAudioElement); + } + else if (this.bellAudioElement) { + this.helperContainer.removeChild(this.bellAudioElement); + } + }; + return Terminal; +}(EventEmitter_1.EventEmitter)); +exports.Terminal = Terminal; +function globalOn(el, type, handler, capture) { + if (!Array.isArray(el)) { + el = [el]; + } + el.forEach(function (element) { + element.addEventListener(type, handler, capture || false); + }); +} +var on = globalOn; +function off(el, type, handler, capture) { + if (capture === void 0) { capture = false; } + el.removeEventListener(type, handler, capture); +} +function isThirdLevelShift(browser, ev) { + var thirdLevelKey = (browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) || + (browser.isMSWindows && ev.altKey && ev.ctrlKey && !ev.metaKey); + if (ev.type === 'keypress') { + return thirdLevelKey; + } + return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47); +} +function wasMondifierKeyOnlyEvent(ev) { + return ev.keyCode === 16 || + ev.keyCode === 17 || + ev.keyCode === 18; +} +var vcolors = (function () { + var result = ColorManager_1.DEFAULT_ANSI_COLORS.map(function (c) { + c = c.substring(1); + return [ + parseInt(c.substring(0, 2), 16), + parseInt(c.substring(2, 4), 16), + parseInt(c.substring(4, 6), 16) + ]; + }); + var r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]; + for (var i = 0; i < 216; i++) { + result.push([ + r[(i / 36) % 6 | 0], + r[(i / 6) % 6 | 0], + r[i % 6] + ]); + } + var c; + for (var i = 0; i < 24; i++) { + c = 8 + i * 10; + result.push([c, c, c]); + } + return result; +})(); +var matchColorCache = {}; +function matchColorDistance(r1, g1, b1, r2, g2, b2) { + return Math.pow(30 * (r1 - r2), 2) + + Math.pow(59 * (g1 - g2), 2) + + Math.pow(11 * (b1 - b2), 2); +} +; +function matchColor_(r1, g1, b1) { + var hash = (r1 << 16) | (g1 << 8) | b1; + if (matchColorCache[hash] != null) { + return matchColorCache[hash]; + } + var ldiff = Infinity; + var li = -1; + var i = 0; + var c; + var r2; + var g2; + var b2; + var diff; + for (; i < vcolors.length; i++) { + c = vcolors[i]; + r2 = c[0]; + g2 = c[1]; + b2 = c[2]; + diff = matchColorDistance(r1, g1, b1, r2, g2, b2); + if (diff === 0) { + li = i; + break; + } + if (diff < ldiff) { + ldiff = diff; + li = i; + } + } + return matchColorCache[hash] = li; +} + + + +},{"./Buffer":1,"./BufferSet":2,"./CompositionHelper":5,"./EscapeSequences":6,"./EventEmitter":7,"./InputHandler":8,"./Linkifier":9,"./Parser":10,"./SelectionManager":11,"./Viewport":15,"./handlers/Clipboard":16,"./input/MouseZoneManager":17,"./renderer/CharAtlas":19,"./renderer/ColorManager":20,"./renderer/Renderer":24,"./utils/Browser":28,"./utils/CharMeasure":29,"./utils/MouseHelper":32,"./utils/Sounds":34}],14:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LinkHoverEventTypes; +(function (LinkHoverEventTypes) { + LinkHoverEventTypes["HOVER"] = "linkhover"; + LinkHoverEventTypes["TOOLTIP"] = "linktooltip"; + LinkHoverEventTypes["LEAVE"] = "linkleave"; +})(LinkHoverEventTypes = exports.LinkHoverEventTypes || (exports.LinkHoverEventTypes = {})); +; + + + +},{}],15:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Viewport = (function () { + function Viewport(terminal, viewportElement, scrollArea, charMeasure) { + var _this = this; + this.terminal = terminal; + this.viewportElement = viewportElement; + this.scrollArea = scrollArea; + this.charMeasure = charMeasure; + this.currentRowHeight = 0; + this.lastRecordedBufferLength = 0; + this.lastRecordedViewportHeight = 0; + this.lastRecordedBufferHeight = 0; + this.viewportElement.addEventListener('scroll', this.onScroll.bind(this)); + setTimeout(function () { return _this.syncScrollArea(); }, 0); + } + Viewport.prototype.onThemeChanged = function (colors) { + this.viewportElement.style.backgroundColor = colors.background; + }; + Viewport.prototype.refresh = function () { + if (this.charMeasure.height > 0) { + this.currentRowHeight = this.terminal.renderer.dimensions.scaledCellHeight / window.devicePixelRatio; + if (this.lastRecordedViewportHeight !== this.terminal.renderer.dimensions.canvasHeight) { + this.lastRecordedViewportHeight = this.terminal.renderer.dimensions.canvasHeight; + this.viewportElement.style.height = this.lastRecordedViewportHeight + 'px'; + } + var newBufferHeight = Math.round(this.currentRowHeight * this.lastRecordedBufferLength); + if (this.lastRecordedBufferHeight !== newBufferHeight) { + this.lastRecordedBufferHeight = newBufferHeight; + this.scrollArea.style.height = this.lastRecordedBufferHeight + 'px'; + } + } + }; + Viewport.prototype.syncScrollArea = function () { + if (this.lastRecordedBufferLength !== this.terminal.buffer.lines.length) { + this.lastRecordedBufferLength = this.terminal.buffer.lines.length; + this.refresh(); + } + else if (this.lastRecordedViewportHeight !== this.terminal.renderer.dimensions.canvasHeight) { + this.refresh(); + } + else { + if (this.terminal.renderer.dimensions.scaledCellHeight / window.devicePixelRatio !== this.currentRowHeight) { + this.refresh(); + } + } + var scrollTop = this.terminal.buffer.ydisp * this.currentRowHeight; + if (this.viewportElement.scrollTop !== scrollTop) { + this.viewportElement.scrollTop = scrollTop; + } + }; + Viewport.prototype.onScroll = function (ev) { + var newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight); + var diff = newRow - this.terminal.buffer.ydisp; + this.terminal.scrollLines(diff, true); + }; + Viewport.prototype.onWheel = function (ev) { + if (ev.deltaY === 0) { + return; + } + var multiplier = 1; + if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) { + multiplier = this.currentRowHeight; + } + else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) { + multiplier = this.currentRowHeight * this.terminal.rows; + } + this.viewportElement.scrollTop += ev.deltaY * multiplier; + ev.preventDefault(); + }; + ; + Viewport.prototype.onTouchStart = function (ev) { + this.lastTouchY = ev.touches[0].pageY; + }; + ; + Viewport.prototype.onTouchMove = function (ev) { + var deltaY = this.lastTouchY - ev.touches[0].pageY; + this.lastTouchY = ev.touches[0].pageY; + if (deltaY === 0) { + return; + } + this.viewportElement.scrollTop += deltaY; + ev.preventDefault(); + }; + ; + return Viewport; +}()); +exports.Viewport = Viewport; + + + +},{}],16:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function prepareTextForTerminal(text, isMSWindows) { + if (isMSWindows) { + return text.replace(/\r?\n/g, '\r'); + } + return text; +} +exports.prepareTextForTerminal = prepareTextForTerminal; +function bracketTextForPaste(text, bracketedPasteMode) { + if (bracketedPasteMode) { + return '\x1b[200~' + text + '\x1b[201~'; + } + return text; +} +exports.bracketTextForPaste = bracketTextForPaste; +function copyHandler(ev, term, selectionManager) { + if (term.browser.isMSIE) { + window.clipboardData.setData('Text', selectionManager.selectionText); + } + else { + ev.clipboardData.setData('text/plain', selectionManager.selectionText); + } + ev.preventDefault(); +} +exports.copyHandler = copyHandler; +function pasteHandler(ev, term) { + ev.stopPropagation(); + var text; + var dispatchPaste = function (text) { + text = prepareTextForTerminal(text, term.browser.isMSWindows); + text = bracketTextForPaste(text, term.bracketedPasteMode); + term.handler(text); + term.textarea.value = ''; + term.emit('paste', text); + term.cancel(ev); + }; + if (term.browser.isMSIE) { + if (window.clipboardData) { + text = window.clipboardData.getData('Text'); + dispatchPaste(text); + } + } + else { + if (ev.clipboardData) { + text = ev.clipboardData.getData('text/plain'); + dispatchPaste(text); + } + } +} +exports.pasteHandler = pasteHandler; +function moveTextAreaUnderMouseCursor(ev, textarea) { + textarea.style.position = 'fixed'; + textarea.style.width = '20px'; + textarea.style.height = '20px'; + textarea.style.left = (ev.clientX - 10) + 'px'; + textarea.style.top = (ev.clientY - 10) + 'px'; + textarea.style.zIndex = '1000'; + textarea.focus(); + setTimeout(function () { + textarea.style.position = null; + textarea.style.width = null; + textarea.style.height = null; + textarea.style.left = null; + textarea.style.top = null; + textarea.style.zIndex = null; + }, 4); +} +exports.moveTextAreaUnderMouseCursor = moveTextAreaUnderMouseCursor; +function rightClickHandler(ev, textarea, selectionManager) { + moveTextAreaUnderMouseCursor(ev, textarea); + textarea.value = selectionManager.selectionText; + textarea.select(); +} +exports.rightClickHandler = rightClickHandler; + + + +},{}],17:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var HOVER_DURATION = 500; +var MouseZoneManager = (function () { + function MouseZoneManager(_terminal) { + var _this = this; + this._terminal = _terminal; + this._zones = []; + this._areZonesActive = false; + this._tooltipTimeout = null; + this._currentZone = null; + this._lastHoverCoords = [null, null]; + this._terminal.element.addEventListener('mousedown', function (e) { return _this._onMouseDown(e); }); + this._mouseMoveListener = function (e) { return _this._onMouseMove(e); }; + this._clickListener = function (e) { return _this._onClick(e); }; + } + MouseZoneManager.prototype.add = function (zone) { + this._zones.push(zone); + if (this._zones.length === 1) { + this._activate(); + } + }; + MouseZoneManager.prototype.clearAll = function (start, end) { + if (this._zones.length === 0) { + return; + } + if (!end) { + start = 0; + end = this._terminal.rows - 1; + } + for (var i = 0; i < this._zones.length; i++) { + var zone = this._zones[i]; + if (zone.y > start && zone.y <= end + 1) { + if (this._currentZone && this._currentZone === zone) { + this._currentZone.leaveCallback(); + this._currentZone = null; + } + this._zones.splice(i--, 1); + } + } + if (this._zones.length === 0) { + this._deactivate(); + } + }; + MouseZoneManager.prototype._activate = function () { + if (!this._areZonesActive) { + this._areZonesActive = true; + this._terminal.element.addEventListener('mousemove', this._mouseMoveListener); + this._terminal.element.addEventListener('click', this._clickListener); + } + }; + MouseZoneManager.prototype._deactivate = function () { + if (this._areZonesActive) { + this._areZonesActive = false; + this._terminal.element.removeEventListener('mousemove', this._mouseMoveListener); + this._terminal.element.removeEventListener('click', this._clickListener); + } + }; + MouseZoneManager.prototype._onMouseMove = function (e) { + if (this._lastHoverCoords[0] !== e.pageX || this._lastHoverCoords[1] !== e.pageY) { + this._onHover(e); + this._lastHoverCoords = [e.pageX, e.pageY]; + } + }; + MouseZoneManager.prototype._onHover = function (e) { + var _this = this; + var zone = this._findZoneEventAt(e); + if (zone === this._currentZone) { + return; + } + if (this._currentZone) { + this._currentZone.leaveCallback(); + this._currentZone = null; + if (this._tooltipTimeout) { + clearTimeout(this._tooltipTimeout); + } + } + if (!zone) { + return; + } + this._currentZone = zone; + if (zone.hoverCallback) { + zone.hoverCallback(e); + } + this._tooltipTimeout = setTimeout(function () { return _this._onTooltip(e); }, HOVER_DURATION); + }; + MouseZoneManager.prototype._onTooltip = function (e) { + this._tooltipTimeout = null; + var zone = this._findZoneEventAt(e); + if (zone && zone.tooltipCallback) { + zone.tooltipCallback(e); + } + }; + MouseZoneManager.prototype._onMouseDown = function (e) { + if (!this._areZonesActive) { + return; + } + var zone = this._findZoneEventAt(e); + if (zone) { + e.preventDefault(); + e.stopImmediatePropagation(); + } + }; + MouseZoneManager.prototype._onClick = function (e) { + var zone = this._findZoneEventAt(e); + if (zone) { + zone.clickCallback(e); + e.preventDefault(); + e.stopImmediatePropagation(); + } + }; + MouseZoneManager.prototype._findZoneEventAt = function (e) { + var coords = this._terminal.mouseHelper.getCoords(e, this._terminal.element, this._terminal.charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows); + if (!coords) { + return null; + } + for (var i = 0; i < this._zones.length; i++) { + var zone = this._zones[i]; + if (zone.y === coords[1] && zone.x1 <= coords[0] && zone.x2 > coords[0]) { + return zone; + } + } + ; + return null; + }; + return MouseZoneManager; +}()); +exports.MouseZoneManager = MouseZoneManager; +var MouseZone = (function () { + function MouseZone(x1, x2, y, clickCallback, hoverCallback, tooltipCallback, leaveCallback) { + this.x1 = x1; + this.x2 = x2; + this.y = y; + this.clickCallback = clickCallback; + this.hoverCallback = hoverCallback; + this.tooltipCallback = tooltipCallback; + this.leaveCallback = leaveCallback; + } + return MouseZone; +}()); +exports.MouseZone = MouseZone; + + + +},{}],18:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var CharAtlas_1 = require("./CharAtlas"); +var Buffer_1 = require("../Buffer"); +exports.INVERTED_DEFAULT_COLOR = -1; +var DIM_OPACITY = 0.5; +var BaseRenderLayer = (function () { + function BaseRenderLayer(container, id, zIndex, _alpha, _colors) { + this._alpha = _alpha; + this._colors = _colors; + this._scaledCharWidth = 0; + this._scaledCharHeight = 0; + this._scaledCellWidth = 0; + this._scaledCellHeight = 0; + this._scaledCharLeft = 0; + this._scaledCharTop = 0; + this._canvas = document.createElement('canvas'); + this._canvas.id = "xterm-" + id + "-layer"; + this._canvas.style.zIndex = zIndex.toString(); + this._ctx = this._canvas.getContext('2d', { alpha: _alpha }); + this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); + if (!_alpha) { + this.clearAll(); + } + container.appendChild(this._canvas); + } + BaseRenderLayer.prototype.onOptionsChanged = function (terminal) { }; + BaseRenderLayer.prototype.onBlur = function (terminal) { }; + BaseRenderLayer.prototype.onFocus = function (terminal) { }; + BaseRenderLayer.prototype.onCursorMove = function (terminal) { }; + BaseRenderLayer.prototype.onGridChanged = function (terminal, startRow, endRow) { }; + BaseRenderLayer.prototype.onSelectionChanged = function (terminal, start, end) { }; + BaseRenderLayer.prototype.onThemeChanged = function (terminal, colorSet) { + this._refreshCharAtlas(terminal, colorSet); + }; + BaseRenderLayer.prototype._refreshCharAtlas = function (terminal, colorSet) { + var _this = this; + if (this._scaledCharWidth <= 0 && this._scaledCharHeight <= 0) { + return; + } + this._charAtlas = null; + var result = CharAtlas_1.acquireCharAtlas(terminal, this._colors, this._scaledCharWidth, this._scaledCharHeight); + if (result instanceof HTMLCanvasElement) { + this._charAtlas = result; + } + else { + result.then(function (bitmap) { return _this._charAtlas = bitmap; }); + } + }; + BaseRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) { + this._scaledCellWidth = dim.scaledCellWidth; + this._scaledCellHeight = dim.scaledCellHeight; + this._scaledCharWidth = dim.scaledCharWidth; + this._scaledCharHeight = dim.scaledCharHeight; + this._scaledCharLeft = dim.scaledCharLeft; + this._scaledCharTop = dim.scaledCharTop; + this._canvas.width = dim.scaledCanvasWidth; + this._canvas.height = dim.scaledCanvasHeight; + this._canvas.style.width = dim.canvasWidth + "px"; + this._canvas.style.height = dim.canvasHeight + "px"; + if (!this._alpha) { + this.clearAll(); + } + if (charSizeChanged) { + this._refreshCharAtlas(terminal, this._colors); + } + }; + BaseRenderLayer.prototype.fillCells = function (x, y, width, height) { + this._ctx.fillRect(x * this._scaledCellWidth, y * this._scaledCellHeight, width * this._scaledCellWidth, height * this._scaledCellHeight); + }; + BaseRenderLayer.prototype.fillBottomLineAtCells = function (x, y, width) { + if (width === void 0) { width = 1; } + this._ctx.fillRect(x * this._scaledCellWidth, (y + 1) * this._scaledCellHeight - window.devicePixelRatio - 1, width * this._scaledCellWidth, window.devicePixelRatio); + }; + BaseRenderLayer.prototype.fillLeftLineAtCell = function (x, y) { + this._ctx.fillRect(x * this._scaledCellWidth, y * this._scaledCellHeight, window.devicePixelRatio, this._scaledCellHeight); + }; + BaseRenderLayer.prototype.strokeRectAtCell = function (x, y, width, height) { + this._ctx.lineWidth = window.devicePixelRatio; + this._ctx.strokeRect(x * this._scaledCellWidth + window.devicePixelRatio / 2, y * this._scaledCellHeight + (window.devicePixelRatio / 2), width * this._scaledCellWidth - window.devicePixelRatio, (height * this._scaledCellHeight) - window.devicePixelRatio); + }; + BaseRenderLayer.prototype.clearAll = function () { + if (this._alpha) { + this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); + } + else { + this._ctx.fillStyle = this._colors.background; + this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height); + } + }; + BaseRenderLayer.prototype.clearCells = function (x, y, width, height) { + if (this._alpha) { + this._ctx.clearRect(x * this._scaledCellWidth, y * this._scaledCellHeight, width * this._scaledCellWidth, height * this._scaledCellHeight); + } + else { + this._ctx.fillStyle = this._colors.background; + this._ctx.fillRect(x * this._scaledCellWidth, y * this._scaledCellHeight, width * this._scaledCellWidth, height * this._scaledCellHeight); + } + }; + BaseRenderLayer.prototype.fillCharTrueColor = function (terminal, charData, x, y) { + this._ctx.font = terminal.options.fontSize * window.devicePixelRatio + "px " + terminal.options.fontFamily; + this._ctx.textBaseline = 'top'; + this._clipRow(terminal, y); + this._ctx.fillText(charData[Buffer_1.CHAR_DATA_CHAR_INDEX], x * this._scaledCellWidth + this._scaledCharLeft, y * this._scaledCellHeight + this._scaledCharTop); + }; + BaseRenderLayer.prototype.drawChar = function (terminal, char, code, width, x, y, fg, bg, bold, dim) { + var colorIndex = 0; + if (fg < 256) { + colorIndex = fg + 2; + } + else { + if (bold && terminal.options.enableBold) { + colorIndex = 1; + } + } + var isAscii = code < 256; + var isBasicColor = (colorIndex > 1 && fg < 16) && (fg < 8 || bold); + var isDefaultColor = fg >= 256; + var isDefaultBackground = bg >= 256; + if (this._charAtlas && isAscii && (isBasicColor || isDefaultColor) && isDefaultBackground) { + var charAtlasCellWidth = this._scaledCharWidth + CharAtlas_1.CHAR_ATLAS_CELL_SPACING; + var charAtlasCellHeight = this._scaledCharHeight + CharAtlas_1.CHAR_ATLAS_CELL_SPACING; + if (dim) { + this._ctx.globalAlpha = DIM_OPACITY; + } + if (bold && !terminal.options.enableBold) { + if (colorIndex > 1) { + colorIndex -= 8; + } + } + this._ctx.drawImage(this._charAtlas, code * charAtlasCellWidth, colorIndex * charAtlasCellHeight, charAtlasCellWidth, this._scaledCharHeight, x * this._scaledCellWidth + this._scaledCharLeft, y * this._scaledCellHeight + this._scaledCharTop, charAtlasCellWidth, this._scaledCharHeight); + } + else { + this._drawUncachedChar(terminal, char, width, fg, x, y, bold, dim); + } + }; + BaseRenderLayer.prototype._drawUncachedChar = function (terminal, char, width, fg, x, y, bold, dim) { + this._ctx.save(); + this._ctx.font = terminal.options.fontSize * window.devicePixelRatio + "px " + terminal.options.fontFamily; + if (bold && terminal.options.enableBold) { + this._ctx.font = "bold " + this._ctx.font; + } + this._ctx.textBaseline = 'top'; + if (fg === exports.INVERTED_DEFAULT_COLOR) { + this._ctx.fillStyle = this._colors.background; + } + else if (fg < 256) { + this._ctx.fillStyle = this._colors.ansi[fg]; + } + else { + this._ctx.fillStyle = this._colors.foreground; + } + this._clipRow(terminal, y); + if (dim) { + this._ctx.globalAlpha = DIM_OPACITY; + } + this._ctx.fillText(char, x * this._scaledCellWidth + this._scaledCharLeft, y * this._scaledCellHeight + this._scaledCharTop); + this._ctx.restore(); + }; + BaseRenderLayer.prototype._clipRow = function (terminal, y) { + this._ctx.beginPath(); + this._ctx.rect(0, y * this._scaledCellHeight, terminal.cols * this._scaledCellWidth, this._scaledCellHeight); + this._ctx.clip(); + }; + return BaseRenderLayer; +}()); +exports.BaseRenderLayer = BaseRenderLayer; + + + +},{"../Buffer":1,"./CharAtlas":19}],19:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Browser_1 = require("../utils/Browser"); +exports.CHAR_ATLAS_CELL_SPACING = 1; +var charAtlasCache = []; +function acquireCharAtlas(terminal, colors, scaledCharWidth, scaledCharHeight) { + var newConfig = generateConfig(scaledCharWidth, scaledCharHeight, terminal, colors); + for (var i = 0; i < charAtlasCache.length; i++) { + var entry = charAtlasCache[i]; + var ownedByIndex = entry.ownedBy.indexOf(terminal); + if (ownedByIndex >= 0) { + if (configEquals(entry.config, newConfig)) { + return entry.bitmap; + } + else { + if (entry.ownedBy.length === 1) { + charAtlasCache.splice(i, 1); + } + else { + entry.ownedBy.splice(ownedByIndex, 1); + } + break; + } + } + } + for (var i = 0; i < charAtlasCache.length; i++) { + var entry = charAtlasCache[i]; + if (configEquals(entry.config, newConfig)) { + entry.ownedBy.push(terminal); + return entry.bitmap; + } + } + var newEntry = { + bitmap: generator.generate(scaledCharWidth, scaledCharHeight, terminal.options.fontSize, terminal.options.fontFamily, colors.background, colors.foreground, colors.ansi), + config: newConfig, + ownedBy: [terminal] + }; + charAtlasCache.push(newEntry); + return newEntry.bitmap; +} +exports.acquireCharAtlas = acquireCharAtlas; +function generateConfig(scaledCharWidth, scaledCharHeight, terminal, colors) { + var clonedColors = { + foreground: colors.foreground, + background: colors.background, + cursor: null, + cursorAccent: null, + selection: null, + ansi: colors.ansi.slice(0, 16) + }; + return { + scaledCharWidth: scaledCharWidth, + scaledCharHeight: scaledCharHeight, + fontFamily: terminal.options.fontFamily, + fontSize: terminal.options.fontSize, + colors: clonedColors + }; +} +function configEquals(a, b) { + for (var i = 0; i < a.colors.ansi.length; i++) { + if (a.colors.ansi[i] !== b.colors.ansi[i]) { + return false; + } + } + return a.fontFamily === b.fontFamily && + a.fontSize === b.fontSize && + a.scaledCharWidth === b.scaledCharWidth && + a.scaledCharHeight === b.scaledCharHeight && + a.colors.foreground === b.colors.foreground && + a.colors.background === b.colors.background; +} +var generator; +function initialize(document, alpha) { + if (!generator) { + generator = new CharAtlasGenerator(document, alpha); + } +} +exports.initialize = initialize; +var CharAtlasGenerator = (function () { + function CharAtlasGenerator(_document, alpha) { + this._document = _document; + this._canvas = this._document.createElement('canvas'); + this._ctx = this._canvas.getContext('2d', { alpha: alpha }); + this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); + } + CharAtlasGenerator.prototype.generate = function (scaledCharWidth, scaledCharHeight, fontSize, fontFamily, background, foreground, ansiColors) { + var cellWidth = scaledCharWidth + exports.CHAR_ATLAS_CELL_SPACING; + var cellHeight = scaledCharHeight + exports.CHAR_ATLAS_CELL_SPACING; + this._canvas.width = 255 * cellWidth; + this._canvas.height = (2 + 16) * cellHeight; + this._ctx.fillStyle = background; + this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height); + this._ctx.save(); + this._ctx.fillStyle = foreground; + this._ctx.font = fontSize * window.devicePixelRatio + "px " + fontFamily; + this._ctx.textBaseline = 'top'; + for (var i = 0; i < 256; i++) { + this._ctx.save(); + this._ctx.beginPath(); + this._ctx.rect(i * cellWidth, 0, cellWidth, cellHeight); + this._ctx.clip(); + this._ctx.fillText(String.fromCharCode(i), i * cellWidth, 0); + this._ctx.restore(); + } + this._ctx.save(); + this._ctx.font = "bold " + this._ctx.font; + for (var i = 0; i < 256; i++) { + this._ctx.save(); + this._ctx.beginPath(); + this._ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight); + this._ctx.clip(); + this._ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight); + this._ctx.restore(); + } + this._ctx.restore(); + this._ctx.font = fontSize * window.devicePixelRatio + "px " + fontFamily; + for (var colorIndex = 0; colorIndex < 16; colorIndex++) { + if (colorIndex === 8) { + this._ctx.font = "bold " + this._ctx.font; + } + var y = (colorIndex + 2) * cellHeight; + for (var i = 0; i < 256; i++) { + this._ctx.save(); + this._ctx.beginPath(); + this._ctx.rect(i * cellWidth, y, cellWidth, cellHeight); + this._ctx.clip(); + this._ctx.fillStyle = ansiColors[colorIndex]; + this._ctx.fillText(String.fromCharCode(i), i * cellWidth, y); + this._ctx.restore(); + } + } + this._ctx.restore(); + if (!('createImageBitmap' in window) || Browser_1.isFirefox) { + var result = this._canvas; + this._canvas = this._document.createElement('canvas'); + this._ctx = this._canvas.getContext('2d'); + this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); + return result; + } + var charAtlasImageData = this._ctx.getImageData(0, 0, this._canvas.width, this._canvas.height); + var r = parseInt(background.substr(1, 2), 16); + var g = parseInt(background.substr(3, 2), 16); + var b = parseInt(background.substr(5, 2), 16); + this._clearColor(charAtlasImageData, r, g, b); + var promise = window.createImageBitmap(charAtlasImageData); + this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); + return promise; + }; + CharAtlasGenerator.prototype._clearColor = function (imageData, r, g, b) { + for (var offset = 0; offset < imageData.data.length; offset += 4) { + if (imageData.data[offset] === r && + imageData.data[offset + 1] === g && + imageData.data[offset + 2] === b) { + imageData.data[offset + 3] = 0; + } + } + }; + return CharAtlasGenerator; +}()); + + + +},{"../utils/Browser":28}],20:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var DEFAULT_FOREGROUND = '#ffffff'; +var DEFAULT_BACKGROUND = '#000000'; +var DEFAULT_CURSOR = '#ffffff'; +var DEFAULT_CURSOR_ACCENT = '#000000'; +var DEFAULT_SELECTION = 'rgba(255, 255, 255, 0.3)'; +exports.DEFAULT_ANSI_COLORS = [ + '#2e3436', + '#cc0000', + '#4e9a06', + '#c4a000', + '#3465a4', + '#75507b', + '#06989a', + '#d3d7cf', + '#555753', + '#ef2929', + '#8ae234', + '#fce94f', + '#729fcf', + '#ad7fa8', + '#34e2e2', + '#eeeeec' +]; +function generate256Colors(first16Colors) { + var colors = first16Colors.slice(); + var v = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]; + for (var i = 0; i < 216; i++) { + var r = toPaddedHex(v[(i / 36) % 6 | 0]); + var g = toPaddedHex(v[(i / 6) % 6 | 0]); + var b = toPaddedHex(v[i % 6]); + colors.push("#" + r + g + b); + } + for (var i = 0; i < 24; i++) { + var c = toPaddedHex(8 + i * 10); + colors.push("#" + c + c + c); + } + return colors; +} +function toPaddedHex(c) { + var s = c.toString(16); + return s.length < 2 ? '0' + s : s; +} +var ColorManager = (function () { + function ColorManager() { + this.colors = { + foreground: DEFAULT_FOREGROUND, + background: DEFAULT_BACKGROUND, + cursor: DEFAULT_CURSOR, + cursorAccent: DEFAULT_CURSOR_ACCENT, + selection: DEFAULT_SELECTION, + ansi: generate256Colors(exports.DEFAULT_ANSI_COLORS) + }; + } + ColorManager.prototype.setTheme = function (theme) { + this.colors.foreground = theme.foreground || DEFAULT_FOREGROUND; + this.colors.background = theme.background || DEFAULT_BACKGROUND; + this.colors.cursor = theme.cursor || DEFAULT_CURSOR; + this.colors.cursorAccent = theme.cursorAccent || DEFAULT_CURSOR_ACCENT; + this.colors.selection = theme.selection || DEFAULT_SELECTION; + this.colors.ansi[0] = theme.black || exports.DEFAULT_ANSI_COLORS[0]; + this.colors.ansi[1] = theme.red || exports.DEFAULT_ANSI_COLORS[1]; + this.colors.ansi[2] = theme.green || exports.DEFAULT_ANSI_COLORS[2]; + this.colors.ansi[3] = theme.yellow || exports.DEFAULT_ANSI_COLORS[3]; + this.colors.ansi[4] = theme.blue || exports.DEFAULT_ANSI_COLORS[4]; + this.colors.ansi[5] = theme.magenta || exports.DEFAULT_ANSI_COLORS[5]; + this.colors.ansi[6] = theme.cyan || exports.DEFAULT_ANSI_COLORS[6]; + this.colors.ansi[7] = theme.white || exports.DEFAULT_ANSI_COLORS[7]; + this.colors.ansi[8] = theme.brightBlack || exports.DEFAULT_ANSI_COLORS[8]; + this.colors.ansi[9] = theme.brightRed || exports.DEFAULT_ANSI_COLORS[9]; + this.colors.ansi[10] = theme.brightGreen || exports.DEFAULT_ANSI_COLORS[10]; + this.colors.ansi[11] = theme.brightYellow || exports.DEFAULT_ANSI_COLORS[11]; + this.colors.ansi[12] = theme.brightBlue || exports.DEFAULT_ANSI_COLORS[12]; + this.colors.ansi[13] = theme.brightMagenta || exports.DEFAULT_ANSI_COLORS[13]; + this.colors.ansi[14] = theme.brightCyan || exports.DEFAULT_ANSI_COLORS[14]; + this.colors.ansi[15] = theme.brightWhite || exports.DEFAULT_ANSI_COLORS[15]; + }; + return ColorManager; +}()); +exports.ColorManager = ColorManager; + + + +},{}],21:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Buffer_1 = require("../Buffer"); +var BaseRenderLayer_1 = require("./BaseRenderLayer"); +var BLINK_INTERVAL = 600; +var CursorRenderLayer = (function (_super) { + __extends(CursorRenderLayer, _super); + function CursorRenderLayer(container, zIndex, colors) { + var _this = _super.call(this, container, 'cursor', zIndex, true, colors) || this; + _this._state = { + x: null, + y: null, + isFocused: null, + style: null, + width: null, + }; + _this._cursorRenderers = { + 'bar': _this._renderBarCursor.bind(_this), + 'block': _this._renderBlockCursor.bind(_this), + 'underline': _this._renderUnderlineCursor.bind(_this) + }; + return _this; + } + CursorRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) { + _super.prototype.resize.call(this, terminal, dim, charSizeChanged); + this._state = { + x: null, + y: null, + isFocused: null, + style: null, + width: null, + }; + }; + CursorRenderLayer.prototype.reset = function (terminal) { + this._clearCursor(); + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.dispose(); + this._cursorBlinkStateManager = null; + this.onOptionsChanged(terminal); + } + }; + CursorRenderLayer.prototype.onBlur = function (terminal) { + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.pause(); + } + terminal.refresh(terminal.buffer.y, terminal.buffer.y); + }; + CursorRenderLayer.prototype.onFocus = function (terminal) { + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.resume(terminal); + } + else { + terminal.refresh(terminal.buffer.y, terminal.buffer.y); + } + }; + CursorRenderLayer.prototype.onOptionsChanged = function (terminal) { + var _this = this; + if (terminal.options.cursorBlink) { + if (!this._cursorBlinkStateManager) { + this._cursorBlinkStateManager = new CursorBlinkStateManager(terminal, function () { + _this._render(terminal, true); + }); + } + } + else { + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.dispose(); + this._cursorBlinkStateManager = null; + } + terminal.refresh(terminal.buffer.y, terminal.buffer.y); + } + }; + CursorRenderLayer.prototype.onCursorMove = function (terminal) { + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.restartBlinkAnimation(terminal); + } + }; + CursorRenderLayer.prototype.onGridChanged = function (terminal, startRow, endRow) { + if (!this._cursorBlinkStateManager || this._cursorBlinkStateManager.isPaused) { + this._render(terminal, false); + } + }; + CursorRenderLayer.prototype._render = function (terminal, triggeredByAnimationFrame) { + if (!terminal.cursorState || terminal.cursorHidden) { + this._clearCursor(); + return; + } + var cursorY = terminal.buffer.ybase + terminal.buffer.y; + var viewportRelativeCursorY = cursorY - terminal.buffer.ydisp; + if (viewportRelativeCursorY < 0 || viewportRelativeCursorY >= terminal.rows) { + this._clearCursor(); + return; + } + var charData = terminal.buffer.lines.get(cursorY)[terminal.buffer.x]; + if (!charData) { + return; + } + if (!terminal.isFocused) { + this._clearCursor(); + this._ctx.save(); + this._ctx.fillStyle = this._colors.cursor; + this._renderBlurCursor(terminal, terminal.buffer.x, viewportRelativeCursorY, charData); + this._ctx.restore(); + this._state.x = terminal.buffer.x; + this._state.y = viewportRelativeCursorY; + this._state.isFocused = false; + this._state.style = terminal.options.cursorStyle; + this._state.width = charData[Buffer_1.CHAR_DATA_WIDTH_INDEX]; + return; + } + if (this._cursorBlinkStateManager && !this._cursorBlinkStateManager.isCursorVisible) { + this._clearCursor(); + return; + } + if (this._state) { + if (this._state.x === terminal.buffer.x && + this._state.y === viewportRelativeCursorY && + this._state.isFocused === terminal.isFocused && + this._state.style === terminal.options.cursorStyle && + this._state.width === charData[Buffer_1.CHAR_DATA_WIDTH_INDEX]) { + return; + } + this._clearCursor(); + } + this._ctx.save(); + this._cursorRenderers[terminal.options.cursorStyle || 'block'](terminal, terminal.buffer.x, viewportRelativeCursorY, charData); + this._ctx.restore(); + this._state.x = terminal.buffer.x; + this._state.y = viewportRelativeCursorY; + this._state.isFocused = false; + this._state.style = terminal.options.cursorStyle; + this._state.width = charData[Buffer_1.CHAR_DATA_WIDTH_INDEX]; + }; + CursorRenderLayer.prototype._clearCursor = function () { + if (this._state) { + this.clearCells(this._state.x, this._state.y, this._state.width, 1); + this._state = { + x: null, + y: null, + isFocused: null, + style: null, + width: null, + }; + } + }; + CursorRenderLayer.prototype._renderBarCursor = function (terminal, x, y, charData) { + this._ctx.save(); + this._ctx.fillStyle = this._colors.cursor; + this.fillLeftLineAtCell(x, y); + this._ctx.restore(); + }; + CursorRenderLayer.prototype._renderBlockCursor = function (terminal, x, y, charData) { + this._ctx.save(); + this._ctx.fillStyle = this._colors.cursor; + this.fillCells(x, y, charData[Buffer_1.CHAR_DATA_WIDTH_INDEX], 1); + this._ctx.fillStyle = this._colors.cursorAccent; + this.fillCharTrueColor(terminal, charData, x, y); + this._ctx.restore(); + }; + CursorRenderLayer.prototype._renderUnderlineCursor = function (terminal, x, y, charData) { + this._ctx.save(); + this._ctx.fillStyle = this._colors.cursor; + this.fillBottomLineAtCells(x, y); + this._ctx.restore(); + }; + CursorRenderLayer.prototype._renderBlurCursor = function (terminal, x, y, charData) { + this._ctx.save(); + this._ctx.strokeStyle = this._colors.cursor; + this.strokeRectAtCell(x, y, charData[Buffer_1.CHAR_DATA_WIDTH_INDEX], 1); + this._ctx.restore(); + }; + return CursorRenderLayer; +}(BaseRenderLayer_1.BaseRenderLayer)); +exports.CursorRenderLayer = CursorRenderLayer; +var CursorBlinkStateManager = (function () { + function CursorBlinkStateManager(terminal, renderCallback) { + this.renderCallback = renderCallback; + this.isCursorVisible = true; + if (terminal.isFocused) { + this._restartInterval(); + } + } + Object.defineProperty(CursorBlinkStateManager.prototype, "isPaused", { + get: function () { return !(this._blinkStartTimeout || this._blinkInterval); }, + enumerable: true, + configurable: true + }); + CursorBlinkStateManager.prototype.dispose = function () { + if (this._blinkInterval) { + window.clearInterval(this._blinkInterval); + this._blinkInterval = null; + } + if (this._blinkStartTimeout) { + window.clearTimeout(this._blinkStartTimeout); + this._blinkStartTimeout = null; + } + if (this._animationFrame) { + window.cancelAnimationFrame(this._animationFrame); + this._animationFrame = null; + } + }; + CursorBlinkStateManager.prototype.restartBlinkAnimation = function (terminal) { + var _this = this; + if (this.isPaused) { + return; + } + this._animationTimeRestarted = Date.now(); + this.isCursorVisible = true; + if (!this._animationFrame) { + this._animationFrame = window.requestAnimationFrame(function () { + _this.renderCallback(); + _this._animationFrame = null; + }); + } + }; + CursorBlinkStateManager.prototype._restartInterval = function (timeToStart) { + var _this = this; + if (timeToStart === void 0) { timeToStart = BLINK_INTERVAL; } + if (this._blinkInterval) { + window.clearInterval(this._blinkInterval); + } + this._blinkStartTimeout = setTimeout(function () { + if (_this._animationTimeRestarted) { + var time = BLINK_INTERVAL - (Date.now() - _this._animationTimeRestarted); + _this._animationTimeRestarted = null; + if (time > 0) { + _this._restartInterval(time); + return; + } + } + _this.isCursorVisible = false; + _this._animationFrame = window.requestAnimationFrame(function () { + _this.renderCallback(); + _this._animationFrame = null; + }); + _this._blinkInterval = setInterval(function () { + if (_this._animationTimeRestarted) { + var time = BLINK_INTERVAL - (Date.now() - _this._animationTimeRestarted); + _this._animationTimeRestarted = null; + _this._restartInterval(time); + return; + } + _this.isCursorVisible = !_this.isCursorVisible; + _this._animationFrame = window.requestAnimationFrame(function () { + _this.renderCallback(); + _this._animationFrame = null; + }); + }, BLINK_INTERVAL); + }, timeToStart); + }; + CursorBlinkStateManager.prototype.pause = function () { + this.isCursorVisible = true; + if (this._blinkInterval) { + window.clearInterval(this._blinkInterval); + this._blinkInterval = null; + } + if (this._blinkStartTimeout) { + window.clearTimeout(this._blinkStartTimeout); + this._blinkStartTimeout = null; + } + if (this._animationFrame) { + window.cancelAnimationFrame(this._animationFrame); + this._animationFrame = null; + } + }; + CursorBlinkStateManager.prototype.resume = function (terminal) { + this._animationTimeRestarted = null; + this._restartInterval(); + this.restartBlinkAnimation(terminal); + }; + return CursorBlinkStateManager; +}()); + + + +},{"../Buffer":1,"./BaseRenderLayer":18}],22:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var GridCache = (function () { + function GridCache() { + this.cache = []; + } + GridCache.prototype.resize = function (width, height) { + for (var x = 0; x < width; x++) { + if (this.cache.length <= x) { + this.cache.push([]); + } + for (var y = this.cache[x].length; y < height; y++) { + this.cache[x].push(null); + } + this.cache[x].length = height; + } + this.cache.length = width; + }; + GridCache.prototype.clear = function () { + for (var x = 0; x < this.cache.length; x++) { + for (var y = 0; y < this.cache[x].length; y++) { + this.cache[x][y] = null; + } + } + }; + return GridCache; +}()); +exports.GridCache = GridCache; + + + +},{}],23:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var BaseRenderLayer_1 = require("./BaseRenderLayer"); +var Types_1 = require("../Types"); +var LinkRenderLayer = (function (_super) { + __extends(LinkRenderLayer, _super); + function LinkRenderLayer(container, zIndex, colors, terminal) { + var _this = _super.call(this, container, 'link', zIndex, true, colors) || this; + _this._state = null; + terminal.linkifier.on(Types_1.LinkHoverEventTypes.HOVER, function (e) { return _this._onLinkHover(e); }); + terminal.linkifier.on(Types_1.LinkHoverEventTypes.LEAVE, function (e) { return _this._onLinkLeave(e); }); + return _this; + } + LinkRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) { + _super.prototype.resize.call(this, terminal, dim, charSizeChanged); + this._state = null; + }; + LinkRenderLayer.prototype.reset = function (terminal) { + this._clearCurrentLink(); + }; + LinkRenderLayer.prototype._clearCurrentLink = function () { + if (this._state) { + this.clearCells(this._state.x, this._state.y, this._state.length, 1); + this._state = null; + } + }; + LinkRenderLayer.prototype._onLinkHover = function (e) { + this._ctx.fillStyle = this._colors.foreground; + this.fillBottomLineAtCells(e.x, e.y, e.length); + this._state = e; + }; + LinkRenderLayer.prototype._onLinkLeave = function (e) { + this._clearCurrentLink(); + }; + return LinkRenderLayer; +}(BaseRenderLayer_1.BaseRenderLayer)); +exports.LinkRenderLayer = LinkRenderLayer; + + + +},{"../Types":14,"./BaseRenderLayer":18}],24:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var TextRenderLayer_1 = require("./TextRenderLayer"); +var SelectionRenderLayer_1 = require("./SelectionRenderLayer"); +var CursorRenderLayer_1 = require("./CursorRenderLayer"); +var ColorManager_1 = require("./ColorManager"); +var LinkRenderLayer_1 = require("./LinkRenderLayer"); +var EventEmitter_1 = require("../EventEmitter"); +var ScreenDprMonitor_1 = require("../utils/ScreenDprMonitor"); +var Renderer = (function (_super) { + __extends(Renderer, _super); + function Renderer(_terminal, theme) { + var _this = _super.call(this) || this; + _this._terminal = _terminal; + _this._refreshRowsQueue = []; + _this._refreshAnimationFrame = null; + _this._isPaused = false; + _this._needsFullRefresh = false; + _this.colorManager = new ColorManager_1.ColorManager(); + if (theme) { + _this.colorManager.setTheme(theme); + } + _this._renderLayers = [ + new TextRenderLayer_1.TextRenderLayer(_this._terminal.element, 0, _this.colorManager.colors, _this._terminal.options.allowTransparency), + new SelectionRenderLayer_1.SelectionRenderLayer(_this._terminal.element, 1, _this.colorManager.colors), + new LinkRenderLayer_1.LinkRenderLayer(_this._terminal.element, 2, _this.colorManager.colors, _this._terminal), + new CursorRenderLayer_1.CursorRenderLayer(_this._terminal.element, 3, _this.colorManager.colors) + ]; + _this.dimensions = { + scaledCharWidth: null, + scaledCharHeight: null, + scaledCellWidth: null, + scaledCellHeight: null, + scaledCharLeft: null, + scaledCharTop: null, + scaledCanvasWidth: null, + scaledCanvasHeight: null, + canvasWidth: null, + canvasHeight: null, + actualCellWidth: null, + actualCellHeight: null + }; + _this._devicePixelRatio = window.devicePixelRatio; + _this._updateDimensions(); + _this._screenDprMonitor = new ScreenDprMonitor_1.ScreenDprMonitor(); + _this._screenDprMonitor.setListener(function () { return _this.onWindowResize(window.devicePixelRatio); }); + if ('IntersectionObserver' in window) { + var observer = new IntersectionObserver(function (e) { return _this.onIntersectionChange(e[0]); }, { threshold: 0 }); + observer.observe(_this._terminal.element); + } + return _this; + } + Renderer.prototype.onIntersectionChange = function (entry) { + this._isPaused = entry.intersectionRatio === 0; + if (!this._isPaused && this._needsFullRefresh) { + this._terminal.refresh(0, this._terminal.rows - 1); + } + }; + Renderer.prototype.onWindowResize = function (devicePixelRatio) { + if (this._devicePixelRatio !== devicePixelRatio) { + this._devicePixelRatio = devicePixelRatio; + this.onResize(this._terminal.cols, this._terminal.rows, true); + } + }; + Renderer.prototype.setTheme = function (theme) { + var _this = this; + this.colorManager.setTheme(theme); + this._renderLayers.forEach(function (l) { + l.onThemeChanged(_this._terminal, _this.colorManager.colors); + l.reset(_this._terminal); + }); + if (this._isPaused) { + this._needsFullRefresh = true; + } + else { + this._terminal.refresh(0, this._terminal.rows - 1); + } + return this.colorManager.colors; + }; + Renderer.prototype.onResize = function (cols, rows, didCharSizeChange) { + var _this = this; + this._updateDimensions(); + this._renderLayers.forEach(function (l) { return l.resize(_this._terminal, _this.dimensions, didCharSizeChange); }); + if (this._isPaused) { + this._needsFullRefresh = true; + } + else { + this._terminal.refresh(0, this._terminal.rows - 1); + } + this.emit('resize', { + width: this.dimensions.canvasWidth, + height: this.dimensions.canvasHeight + }); + }; + Renderer.prototype.onCharSizeChanged = function () { + this.onResize(this._terminal.cols, this._terminal.rows, true); + }; + Renderer.prototype.onBlur = function () { + var _this = this; + this._runOperation(function (l) { return l.onBlur(_this._terminal); }); + }; + Renderer.prototype.onFocus = function () { + var _this = this; + this._runOperation(function (l) { return l.onFocus(_this._terminal); }); + }; + Renderer.prototype.onSelectionChanged = function (start, end) { + var _this = this; + this._runOperation(function (l) { return l.onSelectionChanged(_this._terminal, start, end); }); + }; + Renderer.prototype.onCursorMove = function () { + var _this = this; + this._runOperation(function (l) { return l.onCursorMove(_this._terminal); }); + }; + Renderer.prototype.onOptionsChanged = function () { + var _this = this; + this._runOperation(function (l) { return l.onOptionsChanged(_this._terminal); }); + }; + Renderer.prototype.clear = function () { + var _this = this; + this._runOperation(function (l) { return l.reset(_this._terminal); }); + }; + Renderer.prototype._runOperation = function (operation) { + if (this._isPaused) { + this._needsFullRefresh = true; + } + else { + this._renderLayers.forEach(function (l) { return operation(l); }); + } + }; + Renderer.prototype.queueRefresh = function (start, end) { + if (this._isPaused) { + this._needsFullRefresh = true; + return; + } + this._refreshRowsQueue.push({ start: start, end: end }); + if (!this._refreshAnimationFrame) { + this._refreshAnimationFrame = window.requestAnimationFrame(this._refreshLoop.bind(this)); + } + }; + Renderer.prototype._refreshLoop = function () { + var _this = this; + var start; + var end; + if (this._refreshRowsQueue.length > 4) { + start = 0; + end = this._terminal.rows - 1; + } + else { + start = this._refreshRowsQueue[0].start; + end = this._refreshRowsQueue[0].end; + for (var i = 1; i < this._refreshRowsQueue.length; i++) { + if (this._refreshRowsQueue[i].start < start) { + start = this._refreshRowsQueue[i].start; + } + if (this._refreshRowsQueue[i].end > end) { + end = this._refreshRowsQueue[i].end; + } + } + } + this._refreshRowsQueue = []; + this._refreshAnimationFrame = null; + start = Math.max(start, 0); + end = Math.min(end, this._terminal.rows - 1); + this._renderLayers.forEach(function (l) { return l.onGridChanged(_this._terminal, start, end); }); + this._terminal.emit('refresh', { start: start, end: end }); + }; + Renderer.prototype._updateDimensions = function () { + if (!this._terminal.charMeasure.width || !this._terminal.charMeasure.height) { + return; + } + this.dimensions.scaledCharWidth = Math.floor(this._terminal.charMeasure.width * window.devicePixelRatio); + this.dimensions.scaledCharHeight = Math.ceil(this._terminal.charMeasure.height * window.devicePixelRatio); + this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._terminal.options.lineHeight); + this.dimensions.scaledCharTop = this._terminal.options.lineHeight === 1 ? 0 : Math.round((this.dimensions.scaledCellHeight - this.dimensions.scaledCharHeight) / 2); + this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._terminal.options.letterSpacing); + this.dimensions.scaledCharLeft = Math.floor(this._terminal.options.letterSpacing / 2); + this.dimensions.scaledCanvasHeight = this._terminal.rows * this.dimensions.scaledCellHeight; + this.dimensions.scaledCanvasWidth = this._terminal.cols * this.dimensions.scaledCellWidth; + this.dimensions.canvasHeight = Math.round(this.dimensions.scaledCanvasHeight / window.devicePixelRatio); + this.dimensions.canvasWidth = Math.round(this.dimensions.scaledCanvasWidth / window.devicePixelRatio); + this.dimensions.actualCellHeight = this.dimensions.canvasHeight / this._terminal.rows; + this.dimensions.actualCellWidth = this.dimensions.canvasWidth / this._terminal.cols; + }; + return Renderer; +}(EventEmitter_1.EventEmitter)); +exports.Renderer = Renderer; + + + +},{"../EventEmitter":7,"../utils/ScreenDprMonitor":33,"./ColorManager":20,"./CursorRenderLayer":21,"./LinkRenderLayer":23,"./SelectionRenderLayer":25,"./TextRenderLayer":26}],25:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var BaseRenderLayer_1 = require("./BaseRenderLayer"); +var SelectionRenderLayer = (function (_super) { + __extends(SelectionRenderLayer, _super); + function SelectionRenderLayer(container, zIndex, colors) { + var _this = _super.call(this, container, 'selection', zIndex, true, colors) || this; + _this._state = { + start: null, + end: null + }; + return _this; + } + SelectionRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) { + _super.prototype.resize.call(this, terminal, dim, charSizeChanged); + this._state = { + start: null, + end: null + }; + }; + SelectionRenderLayer.prototype.reset = function (terminal) { + if (this._state.start && this._state.end) { + this._state = { + start: null, + end: null + }; + this.clearAll(); + } + }; + SelectionRenderLayer.prototype.onSelectionChanged = function (terminal, start, end) { + if (this._state.start === start || this._state.end === end) { + return; + } + this.clearAll(); + if (!start || !end) { + return; + } + var viewportStartRow = start[1] - terminal.buffer.ydisp; + var viewportEndRow = end[1] - terminal.buffer.ydisp; + var viewportCappedStartRow = Math.max(viewportStartRow, 0); + var viewportCappedEndRow = Math.min(viewportEndRow, terminal.rows - 1); + if (viewportCappedStartRow >= terminal.rows || viewportCappedEndRow < 0) { + return; + } + var startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0; + var startRowEndCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : terminal.cols; + this._ctx.fillStyle = this._colors.selection; + this.fillCells(startCol, viewportCappedStartRow, startRowEndCol - startCol, 1); + var middleRowsCount = Math.max(viewportCappedEndRow - viewportCappedStartRow - 1, 0); + this.fillCells(0, viewportCappedStartRow + 1, terminal.cols, middleRowsCount); + if (viewportCappedStartRow !== viewportCappedEndRow) { + var endCol = viewportEndRow === viewportCappedEndRow ? end[0] : terminal.cols; + this.fillCells(0, viewportCappedEndRow, endCol, 1); + } + this._state.start = [start[0], start[1]]; + this._state.end = [end[0], end[1]]; + }; + return SelectionRenderLayer; +}(BaseRenderLayer_1.BaseRenderLayer)); +exports.SelectionRenderLayer = SelectionRenderLayer; + + + +},{"./BaseRenderLayer":18}],26:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Buffer_1 = require("../Buffer"); +var Types_1 = require("./Types"); +var GridCache_1 = require("./GridCache"); +var BaseRenderLayer_1 = require("./BaseRenderLayer"); +var OVERLAP_OWNED_CHAR_DATA = [null, '', 0, -1]; +var TextRenderLayer = (function (_super) { + __extends(TextRenderLayer, _super); + function TextRenderLayer(container, zIndex, colors, alpha) { + var _this = _super.call(this, container, 'text', zIndex, alpha, colors) || this; + _this._characterOverlapCache = {}; + _this._state = new GridCache_1.GridCache(); + return _this; + } + TextRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) { + _super.prototype.resize.call(this, terminal, dim, charSizeChanged); + var terminalFont = terminal.options.fontSize * window.devicePixelRatio + "px " + terminal.options.fontFamily; + if (this._characterWidth !== dim.scaledCharWidth || this._characterFont !== terminalFont) { + this._characterWidth = dim.scaledCharWidth; + this._characterFont = terminalFont; + this._characterOverlapCache = {}; + } + this._state.clear(); + this._state.resize(terminal.cols, terminal.rows); + }; + TextRenderLayer.prototype.reset = function (terminal) { + this._state.clear(); + this.clearAll(); + }; + TextRenderLayer.prototype.onGridChanged = function (terminal, startRow, endRow) { + if (this._state.cache.length === 0) { + return; + } + for (var y = startRow; y <= endRow; y++) { + var row = y + terminal.buffer.ydisp; + var line = terminal.buffer.lines.get(row); + this.clearCells(0, y, terminal.cols, 1); + for (var x = 0; x < terminal.cols; x++) { + var charData = line[x]; + var code = charData[Buffer_1.CHAR_DATA_CODE_INDEX]; + var char = charData[Buffer_1.CHAR_DATA_CHAR_INDEX]; + var attr = charData[Buffer_1.CHAR_DATA_ATTR_INDEX]; + var width = charData[Buffer_1.CHAR_DATA_WIDTH_INDEX]; + if (width === 0) { + continue; + } + if (code === 32) { + if (x > 0) { + var previousChar = line[x - 1]; + if (this._isOverlapping(previousChar)) { + continue; + } + } + } + var flags = attr >> 18; + var bg = attr & 0x1ff; + var isDefaultBackground = bg >= 256; + var isInvisible = flags & Types_1.FLAGS.INVISIBLE; + var isInverted = flags & Types_1.FLAGS.INVERSE; + if (!code || (code === 32 && isDefaultBackground && !isInverted) || isInvisible) { + continue; + } + if (width !== 0 && this._isOverlapping(charData)) { + if (x < line.length - 1 && line[x + 1][Buffer_1.CHAR_DATA_CODE_INDEX] === 32) { + width = 2; + } + } + var fg = (attr >> 9) & 0x1ff; + if (isInverted) { + var temp = bg; + bg = fg; + fg = temp; + if (fg === 256) { + fg = BaseRenderLayer_1.INVERTED_DEFAULT_COLOR; + } + if (bg === 257) { + bg = BaseRenderLayer_1.INVERTED_DEFAULT_COLOR; + } + } + if (width === 2) { + } + if (bg < 256) { + this._ctx.save(); + this._ctx.fillStyle = (bg === BaseRenderLayer_1.INVERTED_DEFAULT_COLOR ? this._colors.foreground : this._colors.ansi[bg]); + this.fillCells(x, y, width, 1); + this._ctx.restore(); + } + this._ctx.save(); + if (flags & Types_1.FLAGS.BOLD) { + this._ctx.font = "bold " + this._ctx.font; + if (fg < 8) { + fg += 8; + } + } + if (flags & Types_1.FLAGS.UNDERLINE) { + if (fg === BaseRenderLayer_1.INVERTED_DEFAULT_COLOR) { + this._ctx.fillStyle = this._colors.background; + } + else if (fg < 256) { + this._ctx.fillStyle = this._colors.ansi[fg]; + } + else { + this._ctx.fillStyle = this._colors.foreground; + } + this.fillBottomLineAtCells(x, y); + } + this.drawChar(terminal, char, code, width, x, y, fg, bg, !!(flags & Types_1.FLAGS.BOLD), !!(flags & Types_1.FLAGS.DIM)); + this._ctx.restore(); + } + } + }; + TextRenderLayer.prototype._isOverlapping = function (charData) { + if (charData[Buffer_1.CHAR_DATA_WIDTH_INDEX] !== 1) { + return false; + } + var code = charData[Buffer_1.CHAR_DATA_CODE_INDEX]; + if (code < 256) { + return false; + } + var char = charData[Buffer_1.CHAR_DATA_CHAR_INDEX]; + if (this._characterOverlapCache.hasOwnProperty(char)) { + return this._characterOverlapCache[char]; + } + this._ctx.save(); + this._ctx.font = this._characterFont; + var overlaps = Math.floor(this._ctx.measureText(char).width) > this._characterWidth; + this._ctx.restore(); + this._characterOverlapCache[char] = overlaps; + return overlaps; + }; + TextRenderLayer.prototype._clearChar = function (x, y) { + var colsToClear = 1; + var state = this._state.cache[x][y]; + if (state && state[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 2) { + colsToClear = 2; + } + this.clearCells(x, y, colsToClear, 1); + }; + return TextRenderLayer; +}(BaseRenderLayer_1.BaseRenderLayer)); +exports.TextRenderLayer = TextRenderLayer; + + + +},{"../Buffer":1,"./BaseRenderLayer":18,"./GridCache":22,"./Types":27}],27:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var FLAGS; +(function (FLAGS) { + FLAGS[FLAGS["BOLD"] = 1] = "BOLD"; + FLAGS[FLAGS["UNDERLINE"] = 2] = "UNDERLINE"; + FLAGS[FLAGS["BLINK"] = 4] = "BLINK"; + FLAGS[FLAGS["INVERSE"] = 8] = "INVERSE"; + FLAGS[FLAGS["INVISIBLE"] = 16] = "INVISIBLE"; + FLAGS[FLAGS["DIM"] = 32] = "DIM"; +})(FLAGS = exports.FLAGS || (exports.FLAGS = {})); +; + + + +},{}],28:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Generic_1 = require("./Generic"); +var isNode = (typeof navigator === 'undefined') ? true : false; +var userAgent = (isNode) ? 'node' : navigator.userAgent; +var platform = (isNode) ? 'node' : navigator.platform; +exports.isFirefox = !!~userAgent.indexOf('Firefox'); +exports.isMSIE = !!~userAgent.indexOf('MSIE') || !!~userAgent.indexOf('Trident'); +exports.isMac = Generic_1.contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform); +exports.isIpad = platform === 'iPad'; +exports.isIphone = platform === 'iPhone'; +exports.isMSWindows = Generic_1.contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform); +exports.isLinux = platform.indexOf('Linux') >= 0; + + + +},{"./Generic":31}],29:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var EventEmitter_1 = require("../EventEmitter"); +var CharMeasure = (function (_super) { + __extends(CharMeasure, _super); + function CharMeasure(document, parentElement) { + var _this = _super.call(this) || this; + _this._document = document; + _this._parentElement = parentElement; + _this._measureElement = _this._document.createElement('span'); + _this._measureElement.style.position = 'absolute'; + _this._measureElement.style.top = '0'; + _this._measureElement.style.left = '-9999em'; + _this._measureElement.style.lineHeight = 'normal'; + _this._measureElement.textContent = 'W'; + _this._measureElement.setAttribute('aria-hidden', 'true'); + _this._parentElement.appendChild(_this._measureElement); + return _this; + } + Object.defineProperty(CharMeasure.prototype, "width", { + get: function () { + return this._width; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CharMeasure.prototype, "height", { + get: function () { + return this._height; + }, + enumerable: true, + configurable: true + }); + CharMeasure.prototype.measure = function (options) { + this._measureElement.style.fontFamily = options.fontFamily; + this._measureElement.style.fontSize = options.fontSize + "px"; + var geometry = this._measureElement.getBoundingClientRect(); + if (geometry.width === 0 || geometry.height === 0) { + return; + } + if (this._width !== geometry.width || this._height !== geometry.height) { + this._width = geometry.width; + this._height = Math.ceil(geometry.height); + this.emit('charsizechanged'); + } + }; + return CharMeasure; +}(EventEmitter_1.EventEmitter)); +exports.CharMeasure = CharMeasure; + + + +},{"../EventEmitter":7}],30:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var EventEmitter_1 = require("../EventEmitter"); +var CircularList = (function (_super) { + __extends(CircularList, _super); + function CircularList(_maxLength) { + var _this = _super.call(this) || this; + _this._maxLength = _maxLength; + _this._array = new Array(_this._maxLength); + _this._startIndex = 0; + _this._length = 0; + return _this; + } + Object.defineProperty(CircularList.prototype, "maxLength", { + get: function () { + return this._maxLength; + }, + set: function (newMaxLength) { + if (this._maxLength === newMaxLength) { + return; + } + var newArray = new Array(newMaxLength); + for (var i = 0; i < Math.min(newMaxLength, this.length); i++) { + newArray[i] = this._array[this._getCyclicIndex(i)]; + } + this._array = newArray; + this._maxLength = newMaxLength; + this._startIndex = 0; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CircularList.prototype, "length", { + get: function () { + return this._length; + }, + set: function (newLength) { + if (newLength > this._length) { + for (var i = this._length; i < newLength; i++) { + this._array[i] = undefined; + } + } + this._length = newLength; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CircularList.prototype, "forEach", { + get: function () { + var _this = this; + return function (callbackfn) { + var i = 0; + var length = _this.length; + for (var i_1 = 0; i_1 < length; i_1++) { + callbackfn(_this.get(i_1), i_1); + } + }; + }, + enumerable: true, + configurable: true + }); + CircularList.prototype.get = function (index) { + return this._array[this._getCyclicIndex(index)]; + }; + CircularList.prototype.set = function (index, value) { + this._array[this._getCyclicIndex(index)] = value; + }; + CircularList.prototype.push = function (value) { + this._array[this._getCyclicIndex(this._length)] = value; + if (this._length === this._maxLength) { + this._startIndex++; + if (this._startIndex === this._maxLength) { + this._startIndex = 0; + } + this.emit('trim', 1); + } + else { + this._length++; + } + }; + CircularList.prototype.pop = function () { + return this._array[this._getCyclicIndex(this._length-- - 1)]; + }; + CircularList.prototype.splice = function (start, deleteCount) { + var items = []; + for (var _i = 2; _i < arguments.length; _i++) { + items[_i - 2] = arguments[_i]; + } + if (deleteCount) { + for (var i = start; i < this._length - deleteCount; i++) { + this._array[this._getCyclicIndex(i)] = this._array[this._getCyclicIndex(i + deleteCount)]; + } + this._length -= deleteCount; + } + if (items && items.length) { + for (var i = this._length - 1; i >= start; i--) { + this._array[this._getCyclicIndex(i + items.length)] = this._array[this._getCyclicIndex(i)]; + } + for (var i = 0; i < items.length; i++) { + this._array[this._getCyclicIndex(start + i)] = items[i]; + } + if (this._length + items.length > this.maxLength) { + var countToTrim = (this._length + items.length) - this.maxLength; + this._startIndex += countToTrim; + this._length = this.maxLength; + this.emit('trim', countToTrim); + } + else { + this._length += items.length; + } + } + }; + CircularList.prototype.trimStart = function (count) { + if (count > this._length) { + count = this._length; + } + this._startIndex += count; + this._length -= count; + this.emit('trim', count); + }; + CircularList.prototype.shiftElements = function (start, count, offset) { + if (count <= 0) { + return; + } + if (start < 0 || start >= this._length) { + throw new Error('start argument out of range'); + } + if (start + offset < 0) { + throw new Error('Cannot shift elements in list beyond index 0'); + } + if (offset > 0) { + for (var i = count - 1; i >= 0; i--) { + this.set(start + i + offset, this.get(start + i)); + } + var expandListBy = (start + count + offset) - this._length; + if (expandListBy > 0) { + this._length += expandListBy; + while (this._length > this.maxLength) { + this._length--; + this._startIndex++; + this.emit('trim', 1); + } + } + } + else { + for (var i = 0; i < count; i++) { + this.set(start + i + offset, this.get(start + i)); + } + } + }; + CircularList.prototype._getCyclicIndex = function (index) { + return (this._startIndex + index) % this.maxLength; + }; + return CircularList; +}(EventEmitter_1.EventEmitter)); +exports.CircularList = CircularList; + + + +},{"../EventEmitter":7}],31:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function contains(arr, el) { + return arr.indexOf(el) >= 0; +} +exports.contains = contains; +; + + + +},{}],32:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var MouseHelper = (function () { + function MouseHelper(_renderer) { + this._renderer = _renderer; + } + MouseHelper.getCoordsRelativeToElement = function (event, element) { + if (event.pageX == null) { + return null; + } + var originalElement = element; + var x = event.pageX; + var y = event.pageY; + while (element) { + x -= element.offsetLeft; + y -= element.offsetTop; + element = 'offsetParent' in element ? element.offsetParent : element.parentElement; + } + element = originalElement; + while (element && element !== element.ownerDocument.body) { + x += element.scrollLeft; + y += element.scrollTop; + element = element.parentElement; + } + return [x, y]; + }; + MouseHelper.prototype.getCoords = function (event, element, charMeasure, lineHeight, colCount, rowCount, isSelection) { + if (!charMeasure.width || !charMeasure.height) { + return null; + } + var coords = MouseHelper.getCoordsRelativeToElement(event, element); + if (!coords) { + return null; + } + coords[0] = Math.ceil((coords[0] + (isSelection ? this._renderer.dimensions.actualCellWidth / 2 : 0)) / this._renderer.dimensions.actualCellWidth); + coords[1] = Math.ceil(coords[1] / this._renderer.dimensions.actualCellHeight); + coords[0] = Math.min(Math.max(coords[0], 1), colCount + (isSelection ? 1 : 0)); + coords[1] = Math.min(Math.max(coords[1], 1), rowCount); + return coords; + }; + MouseHelper.prototype.getRawByteCoords = function (event, element, charMeasure, lineHeight, colCount, rowCount) { + var coords = this.getCoords(event, element, charMeasure, lineHeight, colCount, rowCount); + var x = coords[0]; + var y = coords[1]; + x += 32; + y += 32; + return { x: x, y: y }; + }; + return MouseHelper; +}()); +exports.MouseHelper = MouseHelper; + + + +},{}],33:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ScreenDprMonitor = (function () { + function ScreenDprMonitor() { + } + ScreenDprMonitor.prototype.setListener = function (listener) { + var _this = this; + if (this._listener) { + this.clearListener(); + } + this._listener = listener; + this._outerListener = function () { + _this._listener(window.devicePixelRatio, _this._currentDevicePixelRatio); + _this._updateDpr(); + }; + this._updateDpr(); + }; + ScreenDprMonitor.prototype._updateDpr = function () { + if (this._resolutionMediaMatchList) { + this._resolutionMediaMatchList.removeListener(this._outerListener); + } + this._currentDevicePixelRatio = window.devicePixelRatio; + this._resolutionMediaMatchList = window.matchMedia("screen and (resolution: " + window.devicePixelRatio + "dppx)"); + this._resolutionMediaMatchList.addListener(this._outerListener); + }; + ScreenDprMonitor.prototype.clearListener = function () { + if (!this._listener) { + return; + } + this._resolutionMediaMatchList.removeListener(this._outerListener); + this._listener = null; + this._outerListener = null; + }; + return ScreenDprMonitor; +}()); +exports.ScreenDprMonitor = ScreenDprMonitor; + + + +},{}],34:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BellSound = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQBAADpAFgCwAMlBZoG/wdmCcoKRAypDQ8PbRDBEQQTOxRtFYcWlBePGIUZXhoiG88bcBz7HHIdzh0WHlMeZx51HmkeUx4WHs8dah0AHXwc3hs9G4saxRnyGBIYGBcQFv8U4RPAEoYRQBACD70NWwwHC6gJOwjWBloF7gOBAhABkf8b/qv8R/ve+Xf4Ife79W/0JfPZ8Z/wde9N7ijtE+wU6xvqM+lb6H7nw+YX5mrlxuQz5Mzje+Ma49fioeKD4nXiYeJy4pHitOL04j/jn+MN5IPkFOWs5U3mDefM55/ogOl36m7rdOyE7abuyu8D8Unyj/Pg9D/2qfcb+Yn6/vuK/Qj/lAAlAg=='; + + + +},{}],35:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Terminal_1 = require("./Terminal"); +module.exports = Terminal_1.Terminal; + + + +},{"./Terminal":13}]},{},[35])(35) +}); +//# sourceMappingURL=xterm.js.map + + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function attach(term, socket, bidirectional, buffered) { + bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; + term.socket = socket; + term._flushBuffer = function () { + term.write(term._attachSocketBuffer); + term._attachSocketBuffer = null; + }; + term._pushToBuffer = function (data) { + if (term._attachSocketBuffer) { + term._attachSocketBuffer += data; + } + else { + term._attachSocketBuffer = data; + setTimeout(term._flushBuffer, 10); + } + }; + var myTextDecoder; + term._getMessage = function (ev) { + var str; + if (typeof ev.data === "object") { + if (ev.data instanceof ArrayBuffer) { + if (!myTextDecoder) { + myTextDecoder = new TextDecoder(); + } + str = myTextDecoder.decode(ev.data); + } + else { + throw "TODO: handle Blob?"; + } + } + if (buffered) { + term._pushToBuffer(str || ev.data); + } + else { + term.write(str || ev.data); + } + }; + term._sendData = function (data) { + if (socket.readyState !== 1) { + return; + } + socket.send(data); + }; + socket.addEventListener('message', term._getMessage); + if (bidirectional) { + term.on('data', term._sendData); + } + socket.addEventListener('close', term.detach.bind(term, socket)); + socket.addEventListener('error', term.detach.bind(term, socket)); +} +exports.attach = attach; +; +function detach(term, socket) { + term.off('data', term._sendData); + socket = (typeof socket == 'undefined') ? term.socket : socket; + if (socket) { + socket.removeEventListener('message', term._getMessage); + } + delete term.socket; +} +exports.detach = detach; +; +function apply(terminalConstructor) { + terminalConstructor.prototype.attach = function (socket, bidirectional, buffered) { + return attach(this, socket, bidirectional, buffered); + }; + terminalConstructor.prototype.detach = function (socket) { + return detach(this, socket); + }; +} +exports.apply = apply; + +//# sourceMappingURL=attach.js.map + + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function proposeGeometry(term) { + if (!term.element.parentElement) { + return null; + } + var parentElementStyle = window.getComputedStyle(term.element.parentElement); + var parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')); + var parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17); + var elementStyle = window.getComputedStyle(term.element); + var elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')); + var elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')); + var availableHeight = parentElementHeight - elementPaddingVer; + var availableWidth = parentElementWidth - elementPaddingHor; + var geometry = { + cols: Math.floor(availableWidth / term.renderer.dimensions.actualCellWidth), + rows: Math.floor(availableHeight / term.renderer.dimensions.actualCellHeight) + }; + return geometry; +} +exports.proposeGeometry = proposeGeometry; +; +function fit(term) { + var geometry = proposeGeometry(term); + if (geometry) { + if (term.rows !== geometry.rows || term.cols !== geometry.cols) { + term.renderer.clear(); + term.resize(geometry.cols, geometry.rows); + } + } +} +exports.fit = fit; +; +function apply(terminalConstructor) { + terminalConstructor.prototype.proposeGeometry = function () { + return proposeGeometry(this); + }; + terminalConstructor.prototype.fit = function () { + return fit(this); + }; +} +exports.apply = apply; + +//# sourceMappingURL=fit.js.map + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function winptyCompatInit(terminal) { + var isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].indexOf(navigator.platform) >= 0; + if (!isWindows) { + return; + } + terminal.on('linefeed', function () { + var line = terminal.buffer.lines.get(terminal.buffer.ybase + terminal.buffer.y - 1); + var lastChar = line[terminal.cols - 1]; + if (lastChar[3] !== 32) { + var nextLine = terminal.buffer.lines.get(terminal.buffer.ybase + terminal.buffer.y); + nextLine.isWrapped = true; + } + }); +} +exports.winptyCompatInit = winptyCompatInit; +function apply(terminalConstructor) { + terminalConstructor.prototype.winptyCompatInit = function () { + winptyCompatInit(this); + }; +} +exports.apply = apply; + +//# sourceMappingURL=winptyCompat.js.map + + +/***/ }) +/******/ ]); \ No newline at end of file diff --git a/FluentTerminal.Client/dist/index.html b/FluentTerminal.Client/dist/index.html new file mode 100644 index 0000000..196ede2 --- /dev/null +++ b/FluentTerminal.Client/dist/index.html @@ -0,0 +1,12 @@ + + + + + + + + +
+ + + \ No newline at end of file diff --git a/FluentTerminal.Client/dist/style.css b/FluentTerminal.Client/dist/style.css new file mode 100644 index 0000000..41f437c --- /dev/null +++ b/FluentTerminal.Client/dist/style.css @@ -0,0 +1,24 @@ +* { + margin: 0; +} + +html { + -ms-overflow-style: none; + background: transparent; + height: 100%; + } + +body { + background: transparent; + height: 100%; +} + +#terminal-container { + width: 100%; + height: 100%; + margin: 0; +} + +.terminal { + background: transparent !important; +} diff --git a/FluentTerminal.Client/dist/xterm.css b/FluentTerminal.Client/dist/xterm.css new file mode 100644 index 0000000..b3ee50f --- /dev/null +++ b/FluentTerminal.Client/dist/xterm.css @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) + * https://github.com/chjj/term.js + * @license MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Originally forked from (with the author's permission): + * Fabrice Bellard's javascript vt100 for jslinux: + * http://bellard.org/jslinux/ + * Copyright (c) 2011 Fabrice Bellard + * The original design remains. The terminal itself + * has been extended to include xterm CSI codes, among + * other features. + */ + +/** + * Default styles for xterm.js + */ + +.xterm { + font-family: courier-new, courier, monospace; + font-feature-settings: "liga" 0; + position: relative; + user-select: none; + -ms-user-select: none; + -webkit-user-select: none; +} + +.xterm.focus, +.xterm:focus { + outline: none; +} + +.xterm .xterm-helpers { + position: absolute; + top: 0; + /** + * The z-index of the helpers must be higher than the canvases in order for + * IMEs to appear on top. + */ + z-index: 10; +} + +.xterm .xterm-helper-textarea { + /* + * HACK: to fix IE's blinking cursor + * Move textarea out of the screen to the far left, so that the cursor is not visible. + */ + position: absolute; + opacity: 0; + left: -9999em; + top: 0; + width: 0; + height: 0; + z-index: -10; + /** Prevent wrapping so the IME appears against the textarea at the correct position */ + white-space: nowrap; + overflow: hidden; + resize: none; +} + +.xterm .composition-view { + /* TODO: Composition position got messed up somewhere */ + background: #000; + color: #FFF; + display: none; + position: absolute; + white-space: nowrap; + z-index: 1; +} + +.xterm .composition-view.active { + display: block; +} + +.xterm .xterm-viewport { + /* On OS X this is required in order for the scroll bar to appear fully opaque */ + background-color: #000; + overflow-y: scroll; + cursor: default; +} + +.xterm canvas { + position: absolute; + left: 0; + top: 0; +} + +.xterm .xterm-scroll-area { + visibility: hidden; +} + +.xterm .xterm-char-measure-element { + display: inline-block; + visibility: hidden; + position: absolute; + left: -9999em; +} + +.xterm.enable-mouse-events { + /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */ + cursor: default; +} + +.xterm:not(.enable-mouse-events) { + cursor: text; +} diff --git a/FluentTerminal.Client/package-lock.json b/FluentTerminal.Client/package-lock.json new file mode 100644 index 0000000..12a4258 --- /dev/null +++ b/FluentTerminal.Client/package-lock.json @@ -0,0 +1,3104 @@ +{ + "name": "fluent-terminal-client", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "acorn": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", + "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==", + "dev": true + }, + "acorn-dynamic-import": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", + "dev": true, + "requires": { + "acorn": "4.0.13" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "asn1.js": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", + "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "dev": true + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browserify-aes": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", + "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, + "requires": { + "browserify-aes": "1.1.1", + "browserify-des": "1.0.0", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.6" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "1.0.6" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.1.3", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.9" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.0", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.0", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "diffie-hellman": "5.0.2", + "inherits": "2.0.3", + "pbkdf2": "3.0.14", + "public-encrypt": "4.0.0", + "randombytes": "2.0.6", + "randomfill": "1.0.3" + } + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.38" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.6" + } + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "enhanced-resolve": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "object-assign": "4.1.1", + "tapable": "0.2.8" + } + }, + "errno": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", + "integrity": "sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw==", + "dev": true, + "requires": { + "prr": "1.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es5-ext": { + "version": "0.10.38", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.38.tgz", + "integrity": "sha512-jCMyePo7AXbUESwbl8Qi01VSH2piY9s/a3rSU/5w/MlTIx8HPL1xn2InGN8ejt/xulcJgnTO7vqNtOAxzYd2Kg==", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38" + } + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.8.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "json-loader": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + } + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "0.1.6", + "readable-stream": "2.3.3" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "dev": true, + "optional": true + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "1.4.1", + "browserify-zlib": "0.2.0", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "domain-browser": "1.1.7", + "events": "1.1.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.3", + "stream-browserify": "2.0.1", + "stream-http": "2.8.0", + "string_decoder": "1.0.3", + "timers-browserify": "2.0.4", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.2.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, + "requires": { + "asn1.js": "4.9.2", + "browserify-aes": "1.1.1", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.14" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "dev": true, + "requires": { + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "parse-asn1": "5.1.0", + "randombytes": "2.0.6" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "randomfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz", + "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", + "dev": true, + "requires": { + "randombytes": "2.0.6", + "safe-buffer": "5.1.1" + } + }, + "raw-loader": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz", + "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "0.1.4" + } + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "sha.js": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz", + "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "stream-http": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", + "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "tapable": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz", + "integrity": "sha512-uZYhyU3EX8O7HQP+J9fTVYwsq90Vr68xPEFo7yrVImIxYvHgukBEgOB/SgGoorWVTzGM/3Z+wUNnboA4M8jWrg==", + "dev": true, + "requires": { + "setimmediate": "1.0.5" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-js": "2.8.29", + "webpack-sources": "1.1.0" + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "watchpack": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", + "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", + "dev": true, + "requires": { + "async": "2.6.0", + "chokidar": "1.7.0", + "graceful-fs": "4.1.11" + } + }, + "webpack": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.10.0.tgz", + "integrity": "sha512-fxxKXoicjdXNUMY7LIdY89tkJJJ0m1Oo8PQutZ5rLgWbV5QVKI15Cn7+/IHnRTd3vfKfiwBx6SBqlorAuNA8LA==", + "dev": true, + "requires": { + "acorn": "5.3.0", + "acorn-dynamic-import": "2.0.2", + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "async": "2.6.0", + "enhanced-resolve": "3.4.1", + "escope": "3.6.0", + "interpret": "1.1.0", + "json-loader": "0.5.7", + "json5": "0.5.1", + "loader-runner": "2.3.0", + "loader-utils": "1.1.0", + "memory-fs": "0.4.1", + "mkdirp": "0.5.1", + "node-libs-browser": "2.1.0", + "source-map": "0.5.7", + "supports-color": "4.5.0", + "tapable": "0.2.8", + "uglifyjs-webpack-plugin": "0.4.6", + "watchpack": "1.4.0", + "webpack-sources": "1.1.0", + "yargs": "8.0.2" + } + }, + "webpack-sources": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true, + "requires": { + "source-list-map": "2.0.0", + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + } + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + } + } +} diff --git a/FluentTerminal.Client/package.json b/FluentTerminal.Client/package.json new file mode 100644 index 0000000..e76ebca --- /dev/null +++ b/FluentTerminal.Client/package.json @@ -0,0 +1,16 @@ +{ + "name": "fluent-terminal-client", + "version": "1.0.0", + "description": "", + "main": "src/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "xcopy /y /s ..\\xterm.js\\build\\xterm.css dist\\ && npx webpack --config webpack.config.js" + }, + "author": "FS Apps", + "license": "GPL-3.0", + "dependencies": {}, + "devDependencies": { + "webpack": "^3.10.0" + } +} diff --git a/FluentTerminal.Client/src/index.js b/FluentTerminal.Client/src/index.js new file mode 100644 index 0000000..ecbd614 --- /dev/null +++ b/FluentTerminal.Client/src/index.js @@ -0,0 +1,58 @@ +import * as Terminal from '../../xterm.js/build/xterm'; +import * as attach from '../../xterm.js/build/addons/attach/attach'; +import * as fit from '../../xterm.js/build/addons/fit/fit'; +import * as winptyCompat from '../../xterm.js/build/addons/winptyCompat/winptyCompat'; + +Terminal.applyAddon(attach); +Terminal.applyAddon(fit); +Terminal.applyAddon(winptyCompat); + +var term, protocol, socketURL, socket; +var terminalContainer = document.getElementById('terminal-container'); + +createTerminal(); + +function createTerminal() { + while (terminalContainer.children.length) { + terminalContainer.removeChild(terminalContainer.children[0]); + } + term = new Terminal({ + cursorBlink: true, + fontFamily: 'consolas', + fontSize: 13, + allowTransparency: true, + theme: { + background: "transparent" + } + }); + window.term = term; // Expose `term` to window for debugging purposes + term.on('resize', function (size) { + if (!socketURL) { + return; + } + var cols = size.cols, + rows = size.rows, + url = 'http://localhost:9000/terminals/' + pid + '/size?cols=' + cols + '&rows=' + rows; + fetch(url, {method: 'POST'}); + }); + protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://'; + + term.open(terminalContainer); + term.winptyCompatInit(); + term.fit(); + term.focus(); + + fetch('http://localhost:9000/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then(function (res) { + console.log("got response"); + res.text().then(function (url) { + socketURL = JSON.parse(url); + socket = new WebSocket(socketURL); + socket.onopen = runRealTerminal; + }); + }); +} + +function runRealTerminal() { + term.attach(socket); + term._initialized = true; +} diff --git a/FluentTerminal.Client/webpack.config.js b/FluentTerminal.Client/webpack.config.js new file mode 100644 index 0000000..8e4c3ab --- /dev/null +++ b/FluentTerminal.Client/webpack.config.js @@ -0,0 +1,9 @@ +const path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + } +}; \ No newline at end of file diff --git a/FluentTerminal.SystemTray/App.config b/FluentTerminal.SystemTray/App.config new file mode 100644 index 0000000..b4e0aaa --- /dev/null +++ b/FluentTerminal.SystemTray/App.config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/FluentTerminal.SystemTray/BinaryDependencies/x64/winpty-agent.exe b/FluentTerminal.SystemTray/BinaryDependencies/x64/winpty-agent.exe new file mode 100644 index 0000000..f273e3a Binary files /dev/null and b/FluentTerminal.SystemTray/BinaryDependencies/x64/winpty-agent.exe differ diff --git a/FluentTerminal.SystemTray/BinaryDependencies/x64/winpty-debugserver.exe b/FluentTerminal.SystemTray/BinaryDependencies/x64/winpty-debugserver.exe new file mode 100644 index 0000000..8afa0dd Binary files /dev/null and b/FluentTerminal.SystemTray/BinaryDependencies/x64/winpty-debugserver.exe differ diff --git a/FluentTerminal.SystemTray/BinaryDependencies/x64/winpty.dll b/FluentTerminal.SystemTray/BinaryDependencies/x64/winpty.dll new file mode 100644 index 0000000..c16544f Binary files /dev/null and b/FluentTerminal.SystemTray/BinaryDependencies/x64/winpty.dll differ diff --git a/FluentTerminal.SystemTray/BinaryDependencies/x86/winpty-agent.exe b/FluentTerminal.SystemTray/BinaryDependencies/x86/winpty-agent.exe new file mode 100644 index 0000000..925a333 Binary files /dev/null and b/FluentTerminal.SystemTray/BinaryDependencies/x86/winpty-agent.exe differ diff --git a/FluentTerminal.SystemTray/BinaryDependencies/x86/winpty-debugserver.exe b/FluentTerminal.SystemTray/BinaryDependencies/x86/winpty-debugserver.exe new file mode 100644 index 0000000..96a4a2a Binary files /dev/null and b/FluentTerminal.SystemTray/BinaryDependencies/x86/winpty-debugserver.exe differ diff --git a/FluentTerminal.SystemTray/BinaryDependencies/x86/winpty.dll b/FluentTerminal.SystemTray/BinaryDependencies/x86/winpty.dll new file mode 100644 index 0000000..c42a3b5 Binary files /dev/null and b/FluentTerminal.SystemTray/BinaryDependencies/x86/winpty.dll differ diff --git a/FluentTerminal.SystemTray/Client/bundle.js b/FluentTerminal.SystemTray/Client/bundle.js new file mode 100644 index 0000000..04f280a --- /dev/null +++ b/FluentTerminal.SystemTray/Client/bundle.js @@ -0,0 +1,6618 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__xterm_js_build_addons_attach_attach__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__xterm_js_build_addons_attach_attach___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__xterm_js_build_addons_attach_attach__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__xterm_js_build_addons_fit_fit__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__xterm_js_build_addons_fit_fit___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2__xterm_js_build_addons_fit_fit__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__xterm_js_build_addons_winptyCompat_winptyCompat__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__xterm_js_build_addons_winptyCompat_winptyCompat___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3__xterm_js_build_addons_winptyCompat_winptyCompat__); + + + + + +__WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm__["applyAddon"](__WEBPACK_IMPORTED_MODULE_1__xterm_js_build_addons_attach_attach__); +__WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm__["applyAddon"](__WEBPACK_IMPORTED_MODULE_2__xterm_js_build_addons_fit_fit__); +__WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm__["applyAddon"](__WEBPACK_IMPORTED_MODULE_3__xterm_js_build_addons_winptyCompat_winptyCompat__); + +var term, protocol, socketURL, socket; +var terminalContainer = document.getElementById('terminal-container'); + +createTerminal(); + +function createTerminal() { + while (terminalContainer.children.length) { + terminalContainer.removeChild(terminalContainer.children[0]); + } + term = new __WEBPACK_IMPORTED_MODULE_0__xterm_js_build_xterm__({ + cursorBlink: true, + fontFamily: 'consolas', + fontSize: 13, + allowTransparency: true, + theme: { + background: "transparent" + } + }); + window.term = term; // Expose `term` to window for debugging purposes + term.on('resize', function (size) { + if (!socketURL) { + return; + } + var cols = size.cols, + rows = size.rows, + url = 'http://localhost:9000/terminals/' + pid + '/size?cols=' + cols + '&rows=' + rows; + fetch(url, {method: 'POST'}); + }); + protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://'; + + term.open(terminalContainer); + term.winptyCompatInit(); + term.fit(); + term.focus(); + + fetch('http://localhost:9000/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then(function (res) { + console.log("got response"); + res.text().then(function (url) { + socketURL = JSON.parse(url); + socket = new WebSocket(socketURL); + socket.onopen = runRealTerminal; + }); + }); +} + +function runRealTerminal() { + term.attach(socket); + term._initialized = true; +} + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + +var require;var require;(function(f){if(true){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Terminal = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return require(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o this._terminal.rows; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(Buffer.prototype, "isCursorInViewport", { + get: function () { + var absoluteY = this.ybase + this.y; + var relativeY = absoluteY - this.ydisp; + return (relativeY >= 0 && relativeY < this._terminal.rows); + }, + enumerable: true, + configurable: true + }); + Buffer.prototype._getCorrectBufferLength = function (rows) { + if (!this._hasScrollback) { + return rows; + } + var correctBufferLength = rows + this._terminal.options.scrollback; + return correctBufferLength > exports.MAX_BUFFER_SIZE ? exports.MAX_BUFFER_SIZE : correctBufferLength; + }; + Buffer.prototype.fillViewportRows = function () { + if (this._lines.length === 0) { + var i = this._terminal.rows; + while (i--) { + this.lines.push(this._terminal.blankLine()); + } + } + }; + Buffer.prototype.clear = function () { + this.ydisp = 0; + this.ybase = 0; + this.y = 0; + this.x = 0; + this._lines = new CircularList_1.CircularList(this._getCorrectBufferLength(this._terminal.rows)); + this.scrollTop = 0; + this.scrollBottom = this._terminal.rows - 1; + this.setupTabStops(); + }; + Buffer.prototype.resize = function (newCols, newRows) { + var newMaxLength = this._getCorrectBufferLength(newRows); + if (newMaxLength > this._lines.maxLength) { + this._lines.maxLength = newMaxLength; + } + if (this._lines.length > 0) { + if (this._terminal.cols < newCols) { + var ch = [this._terminal.defAttr, ' ', 1, 32]; + for (var i = 0; i < this._lines.length; i++) { + if (this._lines.get(i) === undefined) { + this._lines.set(i, this._terminal.blankLine(undefined, undefined, newCols)); + } + while (this._lines.get(i).length < newCols) { + this._lines.get(i).push(ch); + } + } + } + var addToY = 0; + if (this._terminal.rows < newRows) { + for (var y = this._terminal.rows; y < newRows; y++) { + if (this._lines.length < newRows + this.ybase) { + if (this.ybase > 0 && this._lines.length <= this.ybase + this.y + addToY + 1) { + this.ybase--; + addToY++; + if (this.ydisp > 0) { + this.ydisp--; + } + } + else { + this._lines.push(this._terminal.blankLine(undefined, undefined, newCols)); + } + } + } + } + else { + for (var y = this._terminal.rows; y > newRows; y--) { + if (this._lines.length > newRows + this.ybase) { + if (this._lines.length > this.ybase + this.y + 1) { + this._lines.pop(); + } + else { + this.ybase++; + this.ydisp++; + } + } + } + } + if (newMaxLength < this._lines.maxLength) { + var amountToTrim = this._lines.length - newMaxLength; + if (amountToTrim > 0) { + this._lines.trimStart(amountToTrim); + this.ybase = Math.max(this.ybase - amountToTrim, 0); + this.ydisp = Math.max(this.ydisp - amountToTrim, 0); + } + this._lines.maxLength = newMaxLength; + } + if (this.y >= newRows) { + this.y = newRows - 1; + } + if (addToY) { + this.y += addToY; + } + if (this.x >= newCols) { + this.x = newCols - 1; + } + this.scrollTop = 0; + } + this.scrollBottom = newRows - 1; + }; + Buffer.prototype.translateBufferLineToString = function (lineIndex, trimRight, startCol, endCol) { + if (startCol === void 0) { startCol = 0; } + if (endCol === void 0) { endCol = null; } + var lineString = ''; + var line = this.lines.get(lineIndex); + if (!line) { + return ''; + } + var startIndex = startCol; + endCol = endCol || line.length; + var endIndex = endCol; + for (var i = 0; i < line.length; i++) { + var char = line[i]; + lineString += char[exports.CHAR_DATA_CHAR_INDEX]; + if (char[exports.CHAR_DATA_WIDTH_INDEX] === 0) { + if (startCol >= i) { + startIndex--; + } + if (endCol >= i) { + endIndex--; + } + } + else { + if (char[exports.CHAR_DATA_CHAR_INDEX].length > 1) { + if (startCol > i) { + startIndex += char[exports.CHAR_DATA_CHAR_INDEX].length - 1; + } + if (endCol > i) { + endIndex += char[exports.CHAR_DATA_CHAR_INDEX].length - 1; + } + } + } + } + if (trimRight) { + var rightWhitespaceIndex = lineString.search(/\s+$/); + if (rightWhitespaceIndex !== -1) { + endIndex = Math.min(endIndex, rightWhitespaceIndex); + } + if (endIndex <= startIndex) { + return ''; + } + } + return lineString.substring(startIndex, endIndex); + }; + Buffer.prototype.setupTabStops = function (i) { + if (i != null) { + if (!this.tabs[i]) { + i = this.prevStop(i); + } + } + else { + this.tabs = {}; + i = 0; + } + for (; i < this._terminal.cols; i += this._terminal.options.tabStopWidth) { + this.tabs[i] = true; + } + }; + Buffer.prototype.prevStop = function (x) { + if (x == null) { + x = this.x; + } + while (!this.tabs[--x] && x > 0) + ; + return x >= this._terminal.cols ? this._terminal.cols - 1 : x < 0 ? 0 : x; + }; + Buffer.prototype.nextStop = function (x) { + if (x == null) { + x = this.x; + } + while (!this.tabs[++x] && x < this._terminal.cols) + ; + return x >= this._terminal.cols ? this._terminal.cols - 1 : x < 0 ? 0 : x; + }; + return Buffer; +}()); +exports.Buffer = Buffer; + + + +},{"./utils/CircularList":30}],2:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Buffer_1 = require("./Buffer"); +var EventEmitter_1 = require("./EventEmitter"); +var BufferSet = (function (_super) { + __extends(BufferSet, _super); + function BufferSet(_terminal) { + var _this = _super.call(this) || this; + _this._terminal = _terminal; + _this._normal = new Buffer_1.Buffer(_this._terminal, true); + _this._normal.fillViewportRows(); + _this._alt = new Buffer_1.Buffer(_this._terminal, false); + _this._activeBuffer = _this._normal; + _this.setupTabStops(); + return _this; + } + Object.defineProperty(BufferSet.prototype, "alt", { + get: function () { + return this._alt; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(BufferSet.prototype, "active", { + get: function () { + return this._activeBuffer; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(BufferSet.prototype, "normal", { + get: function () { + return this._normal; + }, + enumerable: true, + configurable: true + }); + BufferSet.prototype.activateNormalBuffer = function () { + this._alt.clear(); + this._activeBuffer = this._normal; + this.emit('activate', this._normal); + }; + BufferSet.prototype.activateAltBuffer = function () { + this._alt.fillViewportRows(); + this._activeBuffer = this._alt; + this.emit('activate', this._alt); + }; + BufferSet.prototype.resize = function (newCols, newRows) { + this._normal.resize(newCols, newRows); + this._alt.resize(newCols, newRows); + }; + BufferSet.prototype.setupTabStops = function (i) { + this._normal.setupTabStops(i); + this._alt.setupTabStops(i); + }; + return BufferSet; +}(EventEmitter_1.EventEmitter)); +exports.BufferSet = BufferSet; + + + +},{"./Buffer":1,"./EventEmitter":7}],3:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.wcwidth = (function (opts) { + var COMBINING_BMP = [ + [0x0300, 0x036F], [0x0483, 0x0486], [0x0488, 0x0489], + [0x0591, 0x05BD], [0x05BF, 0x05BF], [0x05C1, 0x05C2], + [0x05C4, 0x05C5], [0x05C7, 0x05C7], [0x0600, 0x0603], + [0x0610, 0x0615], [0x064B, 0x065E], [0x0670, 0x0670], + [0x06D6, 0x06E4], [0x06E7, 0x06E8], [0x06EA, 0x06ED], + [0x070F, 0x070F], [0x0711, 0x0711], [0x0730, 0x074A], + [0x07A6, 0x07B0], [0x07EB, 0x07F3], [0x0901, 0x0902], + [0x093C, 0x093C], [0x0941, 0x0948], [0x094D, 0x094D], + [0x0951, 0x0954], [0x0962, 0x0963], [0x0981, 0x0981], + [0x09BC, 0x09BC], [0x09C1, 0x09C4], [0x09CD, 0x09CD], + [0x09E2, 0x09E3], [0x0A01, 0x0A02], [0x0A3C, 0x0A3C], + [0x0A41, 0x0A42], [0x0A47, 0x0A48], [0x0A4B, 0x0A4D], + [0x0A70, 0x0A71], [0x0A81, 0x0A82], [0x0ABC, 0x0ABC], + [0x0AC1, 0x0AC5], [0x0AC7, 0x0AC8], [0x0ACD, 0x0ACD], + [0x0AE2, 0x0AE3], [0x0B01, 0x0B01], [0x0B3C, 0x0B3C], + [0x0B3F, 0x0B3F], [0x0B41, 0x0B43], [0x0B4D, 0x0B4D], + [0x0B56, 0x0B56], [0x0B82, 0x0B82], [0x0BC0, 0x0BC0], + [0x0BCD, 0x0BCD], [0x0C3E, 0x0C40], [0x0C46, 0x0C48], + [0x0C4A, 0x0C4D], [0x0C55, 0x0C56], [0x0CBC, 0x0CBC], + [0x0CBF, 0x0CBF], [0x0CC6, 0x0CC6], [0x0CCC, 0x0CCD], + [0x0CE2, 0x0CE3], [0x0D41, 0x0D43], [0x0D4D, 0x0D4D], + [0x0DCA, 0x0DCA], [0x0DD2, 0x0DD4], [0x0DD6, 0x0DD6], + [0x0E31, 0x0E31], [0x0E34, 0x0E3A], [0x0E47, 0x0E4E], + [0x0EB1, 0x0EB1], [0x0EB4, 0x0EB9], [0x0EBB, 0x0EBC], + [0x0EC8, 0x0ECD], [0x0F18, 0x0F19], [0x0F35, 0x0F35], + [0x0F37, 0x0F37], [0x0F39, 0x0F39], [0x0F71, 0x0F7E], + [0x0F80, 0x0F84], [0x0F86, 0x0F87], [0x0F90, 0x0F97], + [0x0F99, 0x0FBC], [0x0FC6, 0x0FC6], [0x102D, 0x1030], + [0x1032, 0x1032], [0x1036, 0x1037], [0x1039, 0x1039], + [0x1058, 0x1059], [0x1160, 0x11FF], [0x135F, 0x135F], + [0x1712, 0x1714], [0x1732, 0x1734], [0x1752, 0x1753], + [0x1772, 0x1773], [0x17B4, 0x17B5], [0x17B7, 0x17BD], + [0x17C6, 0x17C6], [0x17C9, 0x17D3], [0x17DD, 0x17DD], + [0x180B, 0x180D], [0x18A9, 0x18A9], [0x1920, 0x1922], + [0x1927, 0x1928], [0x1932, 0x1932], [0x1939, 0x193B], + [0x1A17, 0x1A18], [0x1B00, 0x1B03], [0x1B34, 0x1B34], + [0x1B36, 0x1B3A], [0x1B3C, 0x1B3C], [0x1B42, 0x1B42], + [0x1B6B, 0x1B73], [0x1DC0, 0x1DCA], [0x1DFE, 0x1DFF], + [0x200B, 0x200F], [0x202A, 0x202E], [0x2060, 0x2063], + [0x206A, 0x206F], [0x20D0, 0x20EF], [0x302A, 0x302F], + [0x3099, 0x309A], [0xA806, 0xA806], [0xA80B, 0xA80B], + [0xA825, 0xA826], [0xFB1E, 0xFB1E], [0xFE00, 0xFE0F], + [0xFE20, 0xFE23], [0xFEFF, 0xFEFF], [0xFFF9, 0xFFFB], + ]; + var COMBINING_HIGH = [ + [0x10A01, 0x10A03], [0x10A05, 0x10A06], [0x10A0C, 0x10A0F], + [0x10A38, 0x10A3A], [0x10A3F, 0x10A3F], [0x1D167, 0x1D169], + [0x1D173, 0x1D182], [0x1D185, 0x1D18B], [0x1D1AA, 0x1D1AD], + [0x1D242, 0x1D244], [0xE0001, 0xE0001], [0xE0020, 0xE007F], + [0xE0100, 0xE01EF] + ]; + function bisearch(ucs, data) { + var min = 0; + var max = data.length - 1; + var mid; + if (ucs < data[0][0] || ucs > data[max][1]) + return false; + while (max >= min) { + mid = (min + max) >> 1; + if (ucs > data[mid][1]) + min = mid + 1; + else if (ucs < data[mid][0]) + max = mid - 1; + else + return true; + } + return false; + } + function wcwidthBMP(ucs) { + if (ucs === 0) + return opts.nul; + if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) + return opts.control; + if (bisearch(ucs, COMBINING_BMP)) + return 0; + if (isWideBMP(ucs)) { + return 2; + } + return 1; + } + function isWideBMP(ucs) { + return (ucs >= 0x1100 && (ucs <= 0x115f || + ucs === 0x2329 || + ucs === 0x232a || + (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs !== 0x303f) || + (ucs >= 0xac00 && ucs <= 0xd7a3) || + (ucs >= 0xf900 && ucs <= 0xfaff) || + (ucs >= 0xfe10 && ucs <= 0xfe19) || + (ucs >= 0xfe30 && ucs <= 0xfe6f) || + (ucs >= 0xff00 && ucs <= 0xff60) || + (ucs >= 0xffe0 && ucs <= 0xffe6))); + } + function wcwidthHigh(ucs) { + if (bisearch(ucs, COMBINING_HIGH)) + return 0; + if ((ucs >= 0x20000 && ucs <= 0x2fffd) || (ucs >= 0x30000 && ucs <= 0x3fffd)) { + return 2; + } + return 1; + } + var control = opts.control | 0; + var table = null; + function init_table() { + var CODEPOINTS = 65536; + var BITWIDTH = 2; + var ITEMSIZE = 32; + var CONTAINERSIZE = CODEPOINTS * BITWIDTH / ITEMSIZE; + var CODEPOINTS_PER_ITEM = ITEMSIZE / BITWIDTH; + table = (typeof Uint32Array === 'undefined') + ? new Array(CONTAINERSIZE) + : new Uint32Array(CONTAINERSIZE); + for (var i = 0; i < CONTAINERSIZE; ++i) { + var num = 0; + var pos = CODEPOINTS_PER_ITEM; + while (pos--) + num = (num << 2) | wcwidthBMP(CODEPOINTS_PER_ITEM * i + pos); + table[i] = num; + } + return table; + } + return function (num) { + num = num | 0; + if (num < 32) + return control | 0; + if (num < 127) + return 1; + var t = table || init_table(); + if (num < 65536) + return t[num >> 4] >> ((num & 15) << 1) & 3; + return wcwidthHigh(num); + }; +})({ nul: 0, control: 0 }); + + + +},{}],4:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.CHARSETS = {}; +exports.DEFAULT_CHARSET = exports.CHARSETS['B']; +exports.CHARSETS['0'] = { + '`': '\u25c6', + 'a': '\u2592', + 'b': '\u0009', + 'c': '\u000c', + 'd': '\u000d', + 'e': '\u000a', + 'f': '\u00b0', + 'g': '\u00b1', + 'h': '\u2424', + 'i': '\u000b', + 'j': '\u2518', + 'k': '\u2510', + 'l': '\u250c', + 'm': '\u2514', + 'n': '\u253c', + 'o': '\u23ba', + 'p': '\u23bb', + 'q': '\u2500', + 'r': '\u23bc', + 's': '\u23bd', + 't': '\u251c', + 'u': '\u2524', + 'v': '\u2534', + 'w': '\u252c', + 'x': '\u2502', + 'y': '\u2264', + 'z': '\u2265', + '{': '\u03c0', + '|': '\u2260', + '}': '\u00a3', + '~': '\u00b7' +}; +exports.CHARSETS['A'] = { + '#': '£' +}; +exports.CHARSETS['B'] = null; +exports.CHARSETS['4'] = { + '#': '£', + '@': '¾', + '[': 'ij', + '\\': '½', + ']': '|', + '{': '¨', + '|': 'f', + '}': '¼', + '~': '´' +}; +exports.CHARSETS['C'] = + exports.CHARSETS['5'] = { + '[': 'Ä', + '\\': 'Ö', + ']': 'Å', + '^': 'Ü', + '`': 'é', + '{': 'ä', + '|': 'ö', + '}': 'å', + '~': 'ü' + }; +exports.CHARSETS['R'] = { + '#': '£', + '@': 'à', + '[': '°', + '\\': 'ç', + ']': '§', + '{': 'é', + '|': 'ù', + '}': 'è', + '~': '¨' +}; +exports.CHARSETS['Q'] = { + '@': 'à', + '[': 'â', + '\\': 'ç', + ']': 'ê', + '^': 'î', + '`': 'ô', + '{': 'é', + '|': 'ù', + '}': 'è', + '~': 'û' +}; +exports.CHARSETS['K'] = { + '@': '§', + '[': 'Ä', + '\\': 'Ö', + ']': 'Ü', + '{': 'ä', + '|': 'ö', + '}': 'ü', + '~': 'ß' +}; +exports.CHARSETS['Y'] = { + '#': '£', + '@': '§', + '[': '°', + '\\': 'ç', + ']': 'é', + '`': 'ù', + '{': 'à', + '|': 'ò', + '}': 'è', + '~': 'ì' +}; +exports.CHARSETS['E'] = + exports.CHARSETS['6'] = { + '@': 'Ä', + '[': 'Æ', + '\\': 'Ø', + ']': 'Å', + '^': 'Ü', + '`': 'ä', + '{': 'æ', + '|': 'ø', + '}': 'å', + '~': 'ü' + }; +exports.CHARSETS['Z'] = { + '#': '£', + '@': '§', + '[': '¡', + '\\': 'Ñ', + ']': '¿', + '{': '°', + '|': 'ñ', + '}': 'ç' +}; +exports.CHARSETS['H'] = + exports.CHARSETS['7'] = { + '@': 'É', + '[': 'Ä', + '\\': 'Ö', + ']': 'Å', + '^': 'Ü', + '`': 'é', + '{': 'ä', + '|': 'ö', + '}': 'å', + '~': 'ü' + }; +exports.CHARSETS['='] = { + '#': 'ù', + '@': 'à', + '[': 'é', + '\\': 'ç', + ']': 'ê', + '^': 'î', + '_': 'è', + '`': 'ô', + '{': 'ä', + '|': 'ö', + '}': 'ü', + '~': 'û' +}; + + + +},{}],5:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var CompositionHelper = (function () { + function CompositionHelper(textarea, compositionView, terminal) { + this.textarea = textarea; + this.compositionView = compositionView; + this.terminal = terminal; + this.isComposing = false; + this.isSendingComposition = false; + this.compositionPosition = { start: null, end: null }; + } + CompositionHelper.prototype.compositionstart = function () { + this.isComposing = true; + this.compositionPosition.start = this.textarea.value.length; + this.compositionView.textContent = ''; + this.compositionView.classList.add('active'); + }; + CompositionHelper.prototype.compositionupdate = function (ev) { + var _this = this; + this.compositionView.textContent = ev.data; + this.updateCompositionElements(); + setTimeout(function () { + _this.compositionPosition.end = _this.textarea.value.length; + }, 0); + }; + CompositionHelper.prototype.compositionend = function () { + this.finalizeComposition(true); + }; + CompositionHelper.prototype.keydown = function (ev) { + if (this.isComposing || this.isSendingComposition) { + if (ev.keyCode === 229) { + return false; + } + else if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) { + return false; + } + else { + this.finalizeComposition(false); + } + } + if (ev.keyCode === 229) { + this.handleAnyTextareaChanges(); + return false; + } + return true; + }; + CompositionHelper.prototype.finalizeComposition = function (waitForPropogation) { + var _this = this; + this.compositionView.classList.remove('active'); + this.isComposing = false; + this.clearTextareaPosition(); + if (!waitForPropogation) { + this.isSendingComposition = false; + var input = this.textarea.value.substring(this.compositionPosition.start, this.compositionPosition.end); + this.terminal.handler(input); + } + else { + var currentCompositionPosition_1 = { + start: this.compositionPosition.start, + end: this.compositionPosition.end, + }; + this.isSendingComposition = true; + setTimeout(function () { + if (_this.isSendingComposition) { + _this.isSendingComposition = false; + var input = void 0; + if (_this.isComposing) { + input = _this.textarea.value.substring(currentCompositionPosition_1.start, currentCompositionPosition_1.end); + } + else { + input = _this.textarea.value.substring(currentCompositionPosition_1.start); + } + _this.terminal.handler(input); + } + }, 0); + } + }; + CompositionHelper.prototype.handleAnyTextareaChanges = function () { + var _this = this; + var oldValue = this.textarea.value; + setTimeout(function () { + if (!_this.isComposing) { + var newValue = _this.textarea.value; + var diff = newValue.replace(oldValue, ''); + if (diff.length > 0) { + _this.terminal.handler(diff); + } + } + }, 0); + }; + CompositionHelper.prototype.updateCompositionElements = function (dontRecurse) { + var _this = this; + if (!this.isComposing) { + return; + } + if (this.terminal.buffer.isCursorInViewport) { + var cellHeight = Math.ceil(this.terminal.charMeasure.height * this.terminal.options.lineHeight); + var cursorTop = this.terminal.buffer.y * cellHeight; + var cursorLeft = this.terminal.buffer.x * this.terminal.charMeasure.width; + this.compositionView.style.left = cursorLeft + 'px'; + this.compositionView.style.top = cursorTop + 'px'; + this.compositionView.style.height = cellHeight + 'px'; + this.compositionView.style.lineHeight = cellHeight + 'px'; + var compositionViewBounds = this.compositionView.getBoundingClientRect(); + this.textarea.style.left = cursorLeft + 'px'; + this.textarea.style.top = cursorTop + 'px'; + this.textarea.style.width = compositionViewBounds.width + 'px'; + this.textarea.style.height = compositionViewBounds.height + 'px'; + this.textarea.style.lineHeight = compositionViewBounds.height + 'px'; + } + if (!dontRecurse) { + setTimeout(function () { return _this.updateCompositionElements(true); }, 0); + } + }; + ; + CompositionHelper.prototype.clearTextareaPosition = function () { + this.textarea.style.left = ''; + this.textarea.style.top = ''; + }; + ; + return CompositionHelper; +}()); +exports.CompositionHelper = CompositionHelper; + + + +},{}],6:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var C0; +(function (C0) { + C0.NUL = '\x00'; + C0.SOH = '\x01'; + C0.STX = '\x02'; + C0.ETX = '\x03'; + C0.EOT = '\x04'; + C0.ENQ = '\x05'; + C0.ACK = '\x06'; + C0.BEL = '\x07'; + C0.BS = '\x08'; + C0.HT = '\x09'; + C0.LF = '\x0a'; + C0.VT = '\x0b'; + C0.FF = '\x0c'; + C0.CR = '\x0d'; + C0.SO = '\x0e'; + C0.SI = '\x0f'; + C0.DLE = '\x10'; + C0.DC1 = '\x11'; + C0.DC2 = '\x12'; + C0.DC3 = '\x13'; + C0.DC4 = '\x14'; + C0.NAK = '\x15'; + C0.SYN = '\x16'; + C0.ETB = '\x17'; + C0.CAN = '\x18'; + C0.EM = '\x19'; + C0.SUB = '\x1a'; + C0.ESC = '\x1b'; + C0.FS = '\x1c'; + C0.GS = '\x1d'; + C0.RS = '\x1e'; + C0.US = '\x1f'; + C0.SP = '\x20'; + C0.DEL = '\x7f'; +})(C0 = exports.C0 || (exports.C0 = {})); +; + + + +},{}],7:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var EventEmitter = (function () { + function EventEmitter() { + this._events = this._events || {}; + } + EventEmitter.prototype.on = function (type, listener) { + this._events[type] = this._events[type] || []; + this._events[type].push(listener); + }; + EventEmitter.prototype.off = function (type, listener) { + if (!this._events[type]) { + return; + } + var obj = this._events[type]; + var i = obj.length; + while (i--) { + if (obj[i] === listener || obj[i].listener === listener) { + obj.splice(i, 1); + return; + } + } + }; + EventEmitter.prototype.removeAllListeners = function (type) { + if (this._events[type]) { + delete this._events[type]; + } + }; + EventEmitter.prototype.once = function (type, listener) { + function on() { + var args = Array.prototype.slice.call(arguments); + this.off(type, on); + listener.apply(this, args); + } + on.listener = listener; + this.on(type, on); + }; + EventEmitter.prototype.emit = function (type) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + if (!this._events[type]) { + return; + } + var obj = this._events[type]; + for (var i = 0; i < obj.length; i++) { + obj[i].apply(this, args); + } + }; + EventEmitter.prototype.listeners = function (type) { + return this._events[type] || []; + }; + EventEmitter.prototype.destroy = function () { + this._events = {}; + }; + return EventEmitter; +}()); +exports.EventEmitter = EventEmitter; + + + +},{}],8:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var EscapeSequences_1 = require("./EscapeSequences"); +var Charsets_1 = require("./Charsets"); +var Buffer_1 = require("./Buffer"); +var Types_1 = require("./renderer/Types"); +var CharWidth_1 = require("./CharWidth"); +var InputHandler = (function () { + function InputHandler(_terminal) { + this._terminal = _terminal; + } + InputHandler.prototype.addChar = function (char, code) { + if (char >= ' ') { + var ch_width = CharWidth_1.wcwidth(code); + if (this._terminal.charset && this._terminal.charset[char]) { + char = this._terminal.charset[char]; + } + var row = this._terminal.buffer.y + this._terminal.buffer.ybase; + if (!ch_width && this._terminal.buffer.x) { + if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1]) { + if (!this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][Buffer_1.CHAR_DATA_WIDTH_INDEX]) { + if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2]) { + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2][Buffer_1.CHAR_DATA_CHAR_INDEX] += char; + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2][3] = char.charCodeAt(0); + } + } + else { + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][Buffer_1.CHAR_DATA_CHAR_INDEX] += char; + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][3] = char.charCodeAt(0); + } + this._terminal.updateRange(this._terminal.buffer.y); + } + return; + } + if (this._terminal.buffer.x + ch_width - 1 >= this._terminal.cols) { + if (this._terminal.wraparoundMode) { + this._terminal.buffer.x = 0; + this._terminal.buffer.y++; + if (this._terminal.buffer.y > this._terminal.buffer.scrollBottom) { + this._terminal.buffer.y--; + this._terminal.scroll(true); + } + else { + this._terminal.buffer.lines.get(this._terminal.buffer.y).isWrapped = true; + } + } + else { + if (ch_width === 2) + return; + } + } + row = this._terminal.buffer.y + this._terminal.buffer.ybase; + if (this._terminal.insertMode) { + for (var moves = 0; moves < ch_width; ++moves) { + var removed = this._terminal.buffer.lines.get(this._terminal.buffer.y + this._terminal.buffer.ybase).pop(); + if (removed[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0 + && this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] + && this._terminal.buffer.lines.get(row)[this._terminal.cols - 2][Buffer_1.CHAR_DATA_WIDTH_INDEX] === 2) { + this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] = [this._terminal.curAttr, ' ', 1, ' '.charCodeAt(0)]; + } + this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 0, [this._terminal.curAttr, ' ', 1, ' '.charCodeAt(0)]); + } + } + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, char, ch_width, char.charCodeAt(0)]; + this._terminal.buffer.x++; + this._terminal.updateRange(this._terminal.buffer.y); + if (ch_width === 2) { + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, '', 0, undefined]; + this._terminal.buffer.x++; + } + } + }; + InputHandler.prototype.bell = function () { + this._terminal.bell(); + }; + InputHandler.prototype.lineFeed = function () { + if (this._terminal.convertEol) { + this._terminal.buffer.x = 0; + } + this._terminal.buffer.y++; + if (this._terminal.buffer.y > this._terminal.buffer.scrollBottom) { + this._terminal.buffer.y--; + this._terminal.scroll(); + } + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x--; + } + this._terminal.emit('linefeed'); + }; + InputHandler.prototype.carriageReturn = function () { + this._terminal.buffer.x = 0; + }; + InputHandler.prototype.backspace = function () { + if (this._terminal.buffer.x > 0) { + this._terminal.buffer.x--; + } + }; + InputHandler.prototype.tab = function () { + this._terminal.buffer.x = this._terminal.buffer.nextStop(); + }; + InputHandler.prototype.shiftOut = function () { + this._terminal.setgLevel(1); + }; + InputHandler.prototype.shiftIn = function () { + this._terminal.setgLevel(0); + }; + InputHandler.prototype.insertChars = function (params) { + var param = params[0]; + if (param < 1) + param = 1; + var row = this._terminal.buffer.y + this._terminal.buffer.ybase; + var j = this._terminal.buffer.x; + var ch = [this._terminal.eraseAttr(), ' ', 1, 32]; + while (param-- && j < this._terminal.cols) { + this._terminal.buffer.lines.get(row).splice(j++, 0, ch); + this._terminal.buffer.lines.get(row).pop(); + } + }; + InputHandler.prototype.cursorUp = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y -= param; + if (this._terminal.buffer.y < 0) { + this._terminal.buffer.y = 0; + } + }; + InputHandler.prototype.cursorDown = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y += param; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x--; + } + }; + InputHandler.prototype.cursorForward = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.x += param; + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x = this._terminal.cols - 1; + } + }; + InputHandler.prototype.cursorBackward = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x--; + } + this._terminal.buffer.x -= param; + if (this._terminal.buffer.x < 0) { + this._terminal.buffer.x = 0; + } + }; + InputHandler.prototype.cursorNextLine = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y += param; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + this._terminal.buffer.x = 0; + }; + InputHandler.prototype.cursorPrecedingLine = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y -= param; + if (this._terminal.buffer.y < 0) { + this._terminal.buffer.y = 0; + } + this._terminal.buffer.x = 0; + }; + InputHandler.prototype.cursorCharAbsolute = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.x = param - 1; + }; + InputHandler.prototype.cursorPosition = function (params) { + var col; + var row = params[0] - 1; + if (params.length >= 2) { + col = params[1] - 1; + } + else { + col = 0; + } + if (row < 0) { + row = 0; + } + else if (row >= this._terminal.rows) { + row = this._terminal.rows - 1; + } + if (col < 0) { + col = 0; + } + else if (col >= this._terminal.cols) { + col = this._terminal.cols - 1; + } + this._terminal.buffer.x = col; + this._terminal.buffer.y = row; + }; + InputHandler.prototype.cursorForwardTab = function (params) { + var param = params[0] || 1; + while (param--) { + this._terminal.buffer.x = this._terminal.buffer.nextStop(); + } + }; + InputHandler.prototype.eraseInDisplay = function (params) { + var j; + switch (params[0]) { + case 0: + this._terminal.eraseRight(this._terminal.buffer.x, this._terminal.buffer.y); + j = this._terminal.buffer.y + 1; + for (; j < this._terminal.rows; j++) { + this._terminal.eraseLine(j); + } + break; + case 1: + this._terminal.eraseLeft(this._terminal.buffer.x, this._terminal.buffer.y); + j = this._terminal.buffer.y; + while (j--) { + this._terminal.eraseLine(j); + } + break; + case 2: + j = this._terminal.rows; + while (j--) + this._terminal.eraseLine(j); + break; + case 3: + var scrollBackSize = this._terminal.buffer.lines.length - this._terminal.rows; + if (scrollBackSize > 0) { + this._terminal.buffer.lines.trimStart(scrollBackSize); + this._terminal.buffer.ybase = Math.max(this._terminal.buffer.ybase - scrollBackSize, 0); + this._terminal.buffer.ydisp = Math.max(this._terminal.buffer.ydisp - scrollBackSize, 0); + this._terminal.emit('scroll', 0); + } + break; + } + }; + InputHandler.prototype.eraseInLine = function (params) { + switch (params[0]) { + case 0: + this._terminal.eraseRight(this._terminal.buffer.x, this._terminal.buffer.y); + break; + case 1: + this._terminal.eraseLeft(this._terminal.buffer.x, this._terminal.buffer.y); + break; + case 2: + this._terminal.eraseLine(this._terminal.buffer.y); + break; + } + }; + InputHandler.prototype.insertLines = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + var row = this._terminal.buffer.y + this._terminal.buffer.ybase; + var scrollBottomRowsOffset = this._terminal.rows - 1 - this._terminal.buffer.scrollBottom; + var scrollBottomAbsolute = this._terminal.rows - 1 + this._terminal.buffer.ybase - scrollBottomRowsOffset + 1; + while (param--) { + this._terminal.buffer.lines.splice(scrollBottomAbsolute - 1, 1); + this._terminal.buffer.lines.splice(row, 0, this._terminal.blankLine(true)); + } + this._terminal.updateRange(this._terminal.buffer.y); + this._terminal.updateRange(this._terminal.buffer.scrollBottom); + }; + InputHandler.prototype.deleteLines = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + var row = this._terminal.buffer.y + this._terminal.buffer.ybase; + var j; + j = this._terminal.rows - 1 - this._terminal.buffer.scrollBottom; + j = this._terminal.rows - 1 + this._terminal.buffer.ybase - j; + while (param--) { + this._terminal.buffer.lines.splice(row, 1); + this._terminal.buffer.lines.splice(j, 0, this._terminal.blankLine(true)); + } + this._terminal.updateRange(this._terminal.buffer.y); + this._terminal.updateRange(this._terminal.buffer.scrollBottom); + }; + InputHandler.prototype.deleteChars = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + var row = this._terminal.buffer.y + this._terminal.buffer.ybase; + var ch = [this._terminal.eraseAttr(), ' ', 1, 32]; + while (param--) { + this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 1); + this._terminal.buffer.lines.get(row).push(ch); + } + this._terminal.updateRange(this._terminal.buffer.y); + }; + InputHandler.prototype.scrollUp = function (params) { + var param = params[0] || 1; + while (param--) { + this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollTop, 1); + this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollBottom, 0, this._terminal.blankLine()); + } + this._terminal.updateRange(this._terminal.buffer.scrollTop); + this._terminal.updateRange(this._terminal.buffer.scrollBottom); + }; + InputHandler.prototype.scrollDown = function (params) { + var param = params[0] || 1; + while (param--) { + this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollBottom, 1); + this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollTop, 0, this._terminal.blankLine()); + } + this._terminal.updateRange(this._terminal.buffer.scrollTop); + this._terminal.updateRange(this._terminal.buffer.scrollBottom); + }; + InputHandler.prototype.eraseChars = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + var row = this._terminal.buffer.y + this._terminal.buffer.ybase; + var j = this._terminal.buffer.x; + var ch = [this._terminal.eraseAttr(), ' ', 1, 32]; + while (param-- && j < this._terminal.cols) { + this._terminal.buffer.lines.get(row)[j++] = ch; + } + }; + InputHandler.prototype.cursorBackwardTab = function (params) { + var param = params[0] || 1; + while (param--) { + this._terminal.buffer.x = this._terminal.buffer.prevStop(); + } + }; + InputHandler.prototype.charPosAbsolute = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.x = param - 1; + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x = this._terminal.cols - 1; + } + }; + InputHandler.prototype.HPositionRelative = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.x += param; + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x = this._terminal.cols - 1; + } + }; + InputHandler.prototype.repeatPrecedingCharacter = function (params) { + var param = params[0] || 1; + var line = this._terminal.buffer.lines.get(this._terminal.buffer.ybase + this._terminal.buffer.y); + var ch = line[this._terminal.buffer.x - 1] || [this._terminal.defAttr, ' ', 1, 32]; + while (param--) { + line[this._terminal.buffer.x++] = ch; + } + }; + InputHandler.prototype.sendDeviceAttributes = function (params) { + if (params[0] > 0) { + return; + } + if (!this._terminal.prefix) { + if (this._terminal.is('xterm') || this._terminal.is('rxvt-unicode') || this._terminal.is('screen')) { + this._terminal.send(EscapeSequences_1.C0.ESC + '[?1;2c'); + } + else if (this._terminal.is('linux')) { + this._terminal.send(EscapeSequences_1.C0.ESC + '[?6c'); + } + } + else if (this._terminal.prefix === '>') { + if (this._terminal.is('xterm')) { + this._terminal.send(EscapeSequences_1.C0.ESC + '[>0;276;0c'); + } + else if (this._terminal.is('rxvt-unicode')) { + this._terminal.send(EscapeSequences_1.C0.ESC + '[>85;95;0c'); + } + else if (this._terminal.is('linux')) { + this._terminal.send(params[0] + 'c'); + } + else if (this._terminal.is('screen')) { + this._terminal.send(EscapeSequences_1.C0.ESC + '[>83;40003;0c'); + } + } + }; + InputHandler.prototype.linePosAbsolute = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y = param - 1; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + }; + InputHandler.prototype.VPositionRelative = function (params) { + var param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y += param; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x--; + } + }; + InputHandler.prototype.HVPosition = function (params) { + if (params[0] < 1) + params[0] = 1; + if (params[1] < 1) + params[1] = 1; + this._terminal.buffer.y = params[0] - 1; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + this._terminal.buffer.x = params[1] - 1; + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x = this._terminal.cols - 1; + } + }; + InputHandler.prototype.tabClear = function (params) { + var param = params[0]; + if (param <= 0) { + delete this._terminal.buffer.tabs[this._terminal.buffer.x]; + } + else if (param === 3) { + this._terminal.buffer.tabs = {}; + } + }; + InputHandler.prototype.setMode = function (params) { + if (params.length > 1) { + for (var i = 0; i < params.length; i++) { + this.setMode([params[i]]); + } + return; + } + if (!this._terminal.prefix) { + switch (params[0]) { + case 4: + this._terminal.insertMode = true; + break; + case 20: + break; + } + } + else if (this._terminal.prefix === '?') { + switch (params[0]) { + case 1: + this._terminal.applicationCursor = true; + break; + case 2: + this._terminal.setgCharset(0, Charsets_1.DEFAULT_CHARSET); + this._terminal.setgCharset(1, Charsets_1.DEFAULT_CHARSET); + this._terminal.setgCharset(2, Charsets_1.DEFAULT_CHARSET); + this._terminal.setgCharset(3, Charsets_1.DEFAULT_CHARSET); + break; + case 3: + this._terminal.savedCols = this._terminal.cols; + this._terminal.resize(132, this._terminal.rows); + break; + case 6: + this._terminal.originMode = true; + break; + case 7: + this._terminal.wraparoundMode = true; + break; + case 12: + break; + case 66: + this._terminal.log('Serial port requested application keypad.'); + this._terminal.applicationKeypad = true; + this._terminal.viewport.syncScrollArea(); + break; + case 9: + case 1000: + case 1002: + case 1003: + this._terminal.x10Mouse = params[0] === 9; + this._terminal.vt200Mouse = params[0] === 1000; + this._terminal.normalMouse = params[0] > 1000; + this._terminal.mouseEvents = true; + this._terminal.element.classList.add('enable-mouse-events'); + this._terminal.selectionManager.disable(); + this._terminal.log('Binding to mouse events.'); + break; + case 1004: + this._terminal.sendFocus = true; + break; + case 1005: + this._terminal.utfMouse = true; + break; + case 1006: + this._terminal.sgrMouse = true; + break; + case 1015: + this._terminal.urxvtMouse = true; + break; + case 25: + this._terminal.cursorHidden = false; + break; + case 1049: + case 47: + case 1047: + this._terminal.buffers.activateAltBuffer(); + this._terminal.selectionManager.setBuffer(this._terminal.buffer); + this._terminal.viewport.syncScrollArea(); + this._terminal.showCursor(); + break; + case 2004: + this._terminal.bracketedPasteMode = true; + break; + } + } + }; + InputHandler.prototype.resetMode = function (params) { + if (params.length > 1) { + for (var i = 0; i < params.length; i++) { + this.resetMode([params[i]]); + } + return; + } + if (!this._terminal.prefix) { + switch (params[0]) { + case 4: + this._terminal.insertMode = false; + break; + case 20: + break; + } + } + else if (this._terminal.prefix === '?') { + switch (params[0]) { + case 1: + this._terminal.applicationCursor = false; + break; + case 3: + if (this._terminal.cols === 132 && this._terminal.savedCols) { + this._terminal.resize(this._terminal.savedCols, this._terminal.rows); + } + delete this._terminal.savedCols; + break; + case 6: + this._terminal.originMode = false; + break; + case 7: + this._terminal.wraparoundMode = false; + break; + case 12: + break; + case 66: + this._terminal.log('Switching back to normal keypad.'); + this._terminal.applicationKeypad = false; + this._terminal.viewport.syncScrollArea(); + break; + case 9: + case 1000: + case 1002: + case 1003: + this._terminal.x10Mouse = false; + this._terminal.vt200Mouse = false; + this._terminal.normalMouse = false; + this._terminal.mouseEvents = false; + this._terminal.element.classList.remove('enable-mouse-events'); + this._terminal.selectionManager.enable(); + break; + case 1004: + this._terminal.sendFocus = false; + break; + case 1005: + this._terminal.utfMouse = false; + break; + case 1006: + this._terminal.sgrMouse = false; + break; + case 1015: + this._terminal.urxvtMouse = false; + break; + case 25: + this._terminal.cursorHidden = true; + break; + case 1049: + case 47: + case 1047: + this._terminal.buffers.activateNormalBuffer(); + this._terminal.selectionManager.setBuffer(this._terminal.buffer); + this._terminal.refresh(0, this._terminal.rows - 1); + this._terminal.viewport.syncScrollArea(); + this._terminal.showCursor(); + break; + case 2004: + this._terminal.bracketedPasteMode = false; + break; + } + } + }; + InputHandler.prototype.charAttributes = function (params) { + if (params.length === 1 && params[0] === 0) { + this._terminal.curAttr = this._terminal.defAttr; + return; + } + var l = params.length; + var flags = this._terminal.curAttr >> 18; + var fg = (this._terminal.curAttr >> 9) & 0x1ff; + var bg = this._terminal.curAttr & 0x1ff; + var p; + for (var i = 0; i < l; i++) { + p = params[i]; + if (p >= 30 && p <= 37) { + fg = p - 30; + } + else if (p >= 40 && p <= 47) { + bg = p - 40; + } + else if (p >= 90 && p <= 97) { + p += 8; + fg = p - 90; + } + else if (p >= 100 && p <= 107) { + p += 8; + bg = p - 100; + } + else if (p === 0) { + flags = this._terminal.defAttr >> 18; + fg = (this._terminal.defAttr >> 9) & 0x1ff; + bg = this._terminal.defAttr & 0x1ff; + } + else if (p === 1) { + flags |= Types_1.FLAGS.BOLD; + } + else if (p === 4) { + flags |= Types_1.FLAGS.UNDERLINE; + } + else if (p === 5) { + flags |= Types_1.FLAGS.BLINK; + } + else if (p === 7) { + flags |= Types_1.FLAGS.INVERSE; + } + else if (p === 8) { + flags |= Types_1.FLAGS.INVISIBLE; + } + else if (p === 2) { + flags |= Types_1.FLAGS.DIM; + } + else if (p === 22) { + flags &= ~Types_1.FLAGS.BOLD; + flags &= ~Types_1.FLAGS.DIM; + } + else if (p === 24) { + flags &= ~Types_1.FLAGS.UNDERLINE; + } + else if (p === 25) { + flags &= ~Types_1.FLAGS.BLINK; + } + else if (p === 27) { + flags &= ~Types_1.FLAGS.INVERSE; + } + else if (p === 28) { + flags &= ~Types_1.FLAGS.INVISIBLE; + } + else if (p === 39) { + fg = (this._terminal.defAttr >> 9) & 0x1ff; + } + else if (p === 49) { + bg = this._terminal.defAttr & 0x1ff; + } + else if (p === 38) { + if (params[i + 1] === 2) { + i += 2; + fg = this._terminal.matchColor(params[i] & 0xff, params[i + 1] & 0xff, params[i + 2] & 0xff); + if (fg === -1) + fg = 0x1ff; + i += 2; + } + else if (params[i + 1] === 5) { + i += 2; + p = params[i] & 0xff; + fg = p; + } + } + else if (p === 48) { + if (params[i + 1] === 2) { + i += 2; + bg = this._terminal.matchColor(params[i] & 0xff, params[i + 1] & 0xff, params[i + 2] & 0xff); + if (bg === -1) + bg = 0x1ff; + i += 2; + } + else if (params[i + 1] === 5) { + i += 2; + p = params[i] & 0xff; + bg = p; + } + } + else if (p === 100) { + fg = (this._terminal.defAttr >> 9) & 0x1ff; + bg = this._terminal.defAttr & 0x1ff; + } + else { + this._terminal.error('Unknown SGR attribute: %d.', p); + } + } + this._terminal.curAttr = (flags << 18) | (fg << 9) | bg; + }; + InputHandler.prototype.deviceStatus = function (params) { + if (!this._terminal.prefix) { + switch (params[0]) { + case 5: + this._terminal.send(EscapeSequences_1.C0.ESC + '[0n'); + break; + case 6: + this._terminal.send(EscapeSequences_1.C0.ESC + '[' + + (this._terminal.buffer.y + 1) + + ';' + + (this._terminal.buffer.x + 1) + + 'R'); + break; + } + } + else if (this._terminal.prefix === '?') { + switch (params[0]) { + case 6: + this._terminal.send(EscapeSequences_1.C0.ESC + '[?' + + (this._terminal.buffer.y + 1) + + ';' + + (this._terminal.buffer.x + 1) + + 'R'); + break; + case 15: + break; + case 25: + break; + case 26: + break; + case 53: + break; + } + } + }; + InputHandler.prototype.softReset = function (params) { + this._terminal.cursorHidden = false; + this._terminal.insertMode = false; + this._terminal.originMode = false; + this._terminal.wraparoundMode = true; + this._terminal.applicationKeypad = false; + this._terminal.viewport.syncScrollArea(); + this._terminal.applicationCursor = false; + this._terminal.buffer.scrollTop = 0; + this._terminal.buffer.scrollBottom = this._terminal.rows - 1; + this._terminal.curAttr = this._terminal.defAttr; + this._terminal.buffer.x = this._terminal.buffer.y = 0; + this._terminal.charset = null; + this._terminal.glevel = 0; + this._terminal.charsets = [null]; + }; + InputHandler.prototype.setCursorStyle = function (params) { + var param = params[0] < 1 ? 1 : params[0]; + switch (param) { + case 1: + case 2: + this._terminal.setOption('cursorStyle', 'block'); + break; + case 3: + case 4: + this._terminal.setOption('cursorStyle', 'underline'); + break; + case 5: + case 6: + this._terminal.setOption('cursorStyle', 'bar'); + break; + } + var isBlinking = param % 2 === 1; + this._terminal.setOption('cursorBlink', isBlinking); + }; + InputHandler.prototype.setScrollRegion = function (params) { + if (this._terminal.prefix) + return; + this._terminal.buffer.scrollTop = (params[0] || 1) - 1; + this._terminal.buffer.scrollBottom = (params[1] && params[1] <= this._terminal.rows ? params[1] : this._terminal.rows) - 1; + this._terminal.buffer.x = 0; + this._terminal.buffer.y = 0; + }; + InputHandler.prototype.saveCursor = function (params) { + this._terminal.buffer.savedX = this._terminal.buffer.x; + this._terminal.buffer.savedY = this._terminal.buffer.y; + }; + InputHandler.prototype.restoreCursor = function (params) { + this._terminal.buffer.x = this._terminal.buffer.savedX || 0; + this._terminal.buffer.y = this._terminal.buffer.savedY || 0; + }; + return InputHandler; +}()); +exports.InputHandler = InputHandler; + + + +},{"./Buffer":1,"./CharWidth":3,"./Charsets":4,"./EscapeSequences":6,"./renderer/Types":27}],9:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Types_1 = require("./Types"); +var MouseZoneManager_1 = require("./input/MouseZoneManager"); +var EventEmitter_1 = require("./EventEmitter"); +var protocolClause = '(https?:\\/\\/)'; +var domainCharacterSet = '[\\da-z\\.-]+'; +var negatedDomainCharacterSet = '[^\\da-z\\.-]+'; +var domainBodyClause = '(' + domainCharacterSet + ')'; +var tldClause = '([a-z\\.]{2,6})'; +var ipClause = '((\\d{1,3}\\.){3}\\d{1,3})'; +var localHostClause = '(localhost)'; +var portClause = '(:\\d{1,5})'; +var hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?'; +var pathClause = '(\\/[\\/\\w\\.\\-%~]*)*'; +var queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*'; +var queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?'; +var hashFragmentClause = '(#' + queryStringHashFragmentCharacterSet + ')?'; +var negatedPathCharacterSet = '[^\\/\\w\\.\\-%]+'; +var bodyClause = hostClause + pathClause + queryStringClause + hashFragmentClause; +var start = '(?:^|' + negatedDomainCharacterSet + ')('; +var end = ')($|' + negatedPathCharacterSet + ')'; +var strictUrlRegex = new RegExp(start + protocolClause + bodyClause + end); +var HYPERTEXT_LINK_MATCHER_ID = 0; +var Linkifier = (function (_super) { + __extends(Linkifier, _super); + function Linkifier(_terminal) { + var _this = _super.call(this) || this; + _this._terminal = _terminal; + _this._linkMatchers = []; + _this._nextLinkMatcherId = HYPERTEXT_LINK_MATCHER_ID; + _this._rowsToLinkify = { + start: null, + end: null + }; + _this.registerLinkMatcher(strictUrlRegex, null, { matchIndex: 1 }); + return _this; + } + Linkifier.prototype.attachToDom = function (mouseZoneManager) { + this._mouseZoneManager = mouseZoneManager; + }; + Linkifier.prototype.linkifyRows = function (start, end) { + var _this = this; + if (!this._mouseZoneManager) { + return; + } + if (!this._rowsToLinkify.start) { + this._rowsToLinkify.start = start; + this._rowsToLinkify.end = end; + } + else { + this._rowsToLinkify.start = this._rowsToLinkify.start < start ? this._rowsToLinkify.start : start; + this._rowsToLinkify.end = this._rowsToLinkify.end > end ? this._rowsToLinkify.end : end; + } + this._mouseZoneManager.clearAll(start, end); + if (this._rowsTimeoutId) { + clearTimeout(this._rowsTimeoutId); + } + this._rowsTimeoutId = setTimeout(function () { return _this._linkifyRows(); }, Linkifier.TIME_BEFORE_LINKIFY); + }; + Linkifier.prototype._linkifyRows = function () { + this._rowsTimeoutId = null; + for (var i = this._rowsToLinkify.start; i <= this._rowsToLinkify.end; i++) { + this._linkifyRow(i); + } + this._rowsToLinkify.start = null; + this._rowsToLinkify.end = null; + }; + Linkifier.prototype.setHypertextLinkHandler = function (handler) { + this._linkMatchers[HYPERTEXT_LINK_MATCHER_ID].handler = handler; + }; + Linkifier.prototype.setHypertextValidationCallback = function (callback) { + this._linkMatchers[HYPERTEXT_LINK_MATCHER_ID].validationCallback = callback; + }; + Linkifier.prototype.registerLinkMatcher = function (regex, handler, options) { + if (options === void 0) { options = {}; } + if (this._nextLinkMatcherId !== HYPERTEXT_LINK_MATCHER_ID && !handler) { + throw new Error('handler must be defined'); + } + var matcher = { + id: this._nextLinkMatcherId++, + regex: regex, + handler: handler, + matchIndex: options.matchIndex, + validationCallback: options.validationCallback, + hoverTooltipCallback: options.tooltipCallback, + hoverLeaveCallback: options.leaveCallback, + priority: options.priority || 0 + }; + this._addLinkMatcherToList(matcher); + return matcher.id; + }; + Linkifier.prototype._addLinkMatcherToList = function (matcher) { + if (this._linkMatchers.length === 0) { + this._linkMatchers.push(matcher); + return; + } + for (var i = this._linkMatchers.length - 1; i >= 0; i--) { + if (matcher.priority <= this._linkMatchers[i].priority) { + this._linkMatchers.splice(i + 1, 0, matcher); + return; + } + } + this._linkMatchers.splice(0, 0, matcher); + }; + Linkifier.prototype.deregisterLinkMatcher = function (matcherId) { + for (var i = 1; i < this._linkMatchers.length; i++) { + if (this._linkMatchers[i].id === matcherId) { + this._linkMatchers.splice(i, 1); + return true; + } + } + return false; + }; + Linkifier.prototype._linkifyRow = function (rowIndex) { + var absoluteRowIndex = this._terminal.buffer.ydisp + rowIndex; + if (absoluteRowIndex >= this._terminal.buffer.lines.length) { + return; + } + var text = this._terminal.buffer.translateBufferLineToString(absoluteRowIndex, false); + for (var i = 0; i < this._linkMatchers.length; i++) { + this._doLinkifyRow(rowIndex, text, this._linkMatchers[i]); + } + }; + Linkifier.prototype._doLinkifyRow = function (rowIndex, text, matcher, offset) { + var _this = this; + if (offset === void 0) { offset = 0; } + var result = []; + var isHttpLinkMatcher = matcher.id === HYPERTEXT_LINK_MATCHER_ID; + var match = text.match(matcher.regex); + if (!match || match.length === 0) { + return; + } + var uri = match[typeof matcher.matchIndex !== 'number' ? 0 : matcher.matchIndex]; + var index = text.indexOf(uri); + if (matcher.validationCallback) { + matcher.validationCallback(uri, function (isValid) { + if (_this._rowsTimeoutId) { + return; + } + if (isValid) { + _this._addLink(offset + index, rowIndex, uri, matcher); + } + }); + } + else { + this._addLink(offset + index, rowIndex, uri, matcher); + } + var remainingStartIndex = index + uri.length; + var remainingText = text.substr(remainingStartIndex); + if (remainingText.length > 0) { + this._doLinkifyRow(rowIndex, remainingText, matcher, offset + remainingStartIndex); + } + }; + Linkifier.prototype._addLink = function (x, y, uri, matcher) { + var _this = this; + this._mouseZoneManager.add(new MouseZoneManager_1.MouseZone(x + 1, x + 1 + uri.length, y + 1, function (e) { + if (matcher.handler) { + return matcher.handler(e, uri); + } + window.open(uri, '_blank'); + }, function (e) { + _this.emit(Types_1.LinkHoverEventTypes.HOVER, { x: x, y: y, length: uri.length }); + _this._terminal.element.style.cursor = 'pointer'; + }, function (e) { + _this.emit(Types_1.LinkHoverEventTypes.TOOLTIP, { x: x, y: y, length: uri.length }); + if (matcher.hoverTooltipCallback) { + matcher.hoverTooltipCallback(e, uri); + } + }, function () { + _this.emit(Types_1.LinkHoverEventTypes.LEAVE, { x: x, y: y, length: uri.length }); + _this._terminal.element.style.cursor = ''; + if (matcher.hoverLeaveCallback) { + matcher.hoverLeaveCallback(); + } + })); + }; + Linkifier.TIME_BEFORE_LINKIFY = 200; + return Linkifier; +}(EventEmitter_1.EventEmitter)); +exports.Linkifier = Linkifier; + + + +},{"./EventEmitter":7,"./Types":14,"./input/MouseZoneManager":17}],10:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var EscapeSequences_1 = require("./EscapeSequences"); +var Charsets_1 = require("./Charsets"); +var normalStateHandler = {}; +normalStateHandler[EscapeSequences_1.C0.BEL] = function (parser, handler) { return handler.bell(); }; +normalStateHandler[EscapeSequences_1.C0.LF] = function (parser, handler) { return handler.lineFeed(); }; +normalStateHandler[EscapeSequences_1.C0.VT] = normalStateHandler[EscapeSequences_1.C0.LF]; +normalStateHandler[EscapeSequences_1.C0.FF] = normalStateHandler[EscapeSequences_1.C0.LF]; +normalStateHandler[EscapeSequences_1.C0.CR] = function (parser, handler) { return handler.carriageReturn(); }; +normalStateHandler[EscapeSequences_1.C0.BS] = function (parser, handler) { return handler.backspace(); }; +normalStateHandler[EscapeSequences_1.C0.HT] = function (parser, handler) { return handler.tab(); }; +normalStateHandler[EscapeSequences_1.C0.SO] = function (parser, handler) { return handler.shiftOut(); }; +normalStateHandler[EscapeSequences_1.C0.SI] = function (parser, handler) { return handler.shiftIn(); }; +normalStateHandler[EscapeSequences_1.C0.ESC] = function (parser, handler) { return parser.setState(ParserState.ESCAPED); }; +var escapedStateHandler = {}; +escapedStateHandler['['] = function (parser, terminal) { + terminal.params = []; + terminal.currentParam = 0; + parser.setState(ParserState.CSI_PARAM); +}; +escapedStateHandler[']'] = function (parser, terminal) { + terminal.params = []; + terminal.currentParam = 0; + parser.setState(ParserState.OSC); +}; +escapedStateHandler['P'] = function (parser, terminal) { + terminal.params = []; + terminal.currentParam = 0; + parser.setState(ParserState.DCS); +}; +escapedStateHandler['_'] = function (parser, terminal) { + parser.setState(ParserState.IGNORE); +}; +escapedStateHandler['^'] = function (parser, terminal) { + parser.setState(ParserState.IGNORE); +}; +escapedStateHandler['c'] = function (parser, terminal) { + terminal.reset(); +}; +escapedStateHandler['E'] = function (parser, terminal) { + terminal.buffer.x = 0; + terminal.index(); + parser.setState(ParserState.NORMAL); +}; +escapedStateHandler['D'] = function (parser, terminal) { + terminal.index(); + parser.setState(ParserState.NORMAL); +}; +escapedStateHandler['M'] = function (parser, terminal) { + terminal.reverseIndex(); + parser.setState(ParserState.NORMAL); +}; +escapedStateHandler['%'] = function (parser, terminal) { + terminal.setgLevel(0); + terminal.setgCharset(0, Charsets_1.DEFAULT_CHARSET); + parser.setState(ParserState.NORMAL); + parser.skipNextChar(); +}; +escapedStateHandler[EscapeSequences_1.C0.CAN] = function (parser) { return parser.setState(ParserState.NORMAL); }; +var csiParamStateHandler = {}; +csiParamStateHandler['?'] = function (parser) { return parser.setPrefix('?'); }; +csiParamStateHandler['>'] = function (parser) { return parser.setPrefix('>'); }; +csiParamStateHandler['!'] = function (parser) { return parser.setPrefix('!'); }; +csiParamStateHandler['0'] = function (parser) { return parser.setParam(parser.getParam() * 10); }; +csiParamStateHandler['1'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 1); }; +csiParamStateHandler['2'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 2); }; +csiParamStateHandler['3'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 3); }; +csiParamStateHandler['4'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 4); }; +csiParamStateHandler['5'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 5); }; +csiParamStateHandler['6'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 6); }; +csiParamStateHandler['7'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 7); }; +csiParamStateHandler['8'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 8); }; +csiParamStateHandler['9'] = function (parser) { return parser.setParam(parser.getParam() * 10 + 9); }; +csiParamStateHandler['$'] = function (parser) { return parser.setPostfix('$'); }; +csiParamStateHandler['"'] = function (parser) { return parser.setPostfix('"'); }; +csiParamStateHandler[' '] = function (parser) { return parser.setPostfix(' '); }; +csiParamStateHandler['\''] = function (parser) { return parser.setPostfix('\''); }; +csiParamStateHandler[';'] = function (parser) { return parser.finalizeParam(); }; +csiParamStateHandler[EscapeSequences_1.C0.CAN] = function (parser) { return parser.setState(ParserState.NORMAL); }; +var csiStateHandler = {}; +csiStateHandler['@'] = function (handler, params, prefix) { return handler.insertChars(params); }; +csiStateHandler['A'] = function (handler, params, prefix) { return handler.cursorUp(params); }; +csiStateHandler['B'] = function (handler, params, prefix) { return handler.cursorDown(params); }; +csiStateHandler['C'] = function (handler, params, prefix) { return handler.cursorForward(params); }; +csiStateHandler['D'] = function (handler, params, prefix) { return handler.cursorBackward(params); }; +csiStateHandler['E'] = function (handler, params, prefix) { return handler.cursorNextLine(params); }; +csiStateHandler['F'] = function (handler, params, prefix) { return handler.cursorPrecedingLine(params); }; +csiStateHandler['G'] = function (handler, params, prefix) { return handler.cursorCharAbsolute(params); }; +csiStateHandler['H'] = function (handler, params, prefix) { return handler.cursorPosition(params); }; +csiStateHandler['I'] = function (handler, params, prefix) { return handler.cursorForwardTab(params); }; +csiStateHandler['J'] = function (handler, params, prefix) { return handler.eraseInDisplay(params); }; +csiStateHandler['K'] = function (handler, params, prefix) { return handler.eraseInLine(params); }; +csiStateHandler['L'] = function (handler, params, prefix) { return handler.insertLines(params); }; +csiStateHandler['M'] = function (handler, params, prefix) { return handler.deleteLines(params); }; +csiStateHandler['P'] = function (handler, params, prefix) { return handler.deleteChars(params); }; +csiStateHandler['S'] = function (handler, params, prefix) { return handler.scrollUp(params); }; +csiStateHandler['T'] = function (handler, params, prefix) { + if (params.length < 2 && !prefix) { + handler.scrollDown(params); + } +}; +csiStateHandler['X'] = function (handler, params, prefix) { return handler.eraseChars(params); }; +csiStateHandler['Z'] = function (handler, params, prefix) { return handler.cursorBackwardTab(params); }; +csiStateHandler['`'] = function (handler, params, prefix) { return handler.charPosAbsolute(params); }; +csiStateHandler['a'] = function (handler, params, prefix) { return handler.HPositionRelative(params); }; +csiStateHandler['b'] = function (handler, params, prefix) { return handler.repeatPrecedingCharacter(params); }; +csiStateHandler['c'] = function (handler, params, prefix) { return handler.sendDeviceAttributes(params); }; +csiStateHandler['d'] = function (handler, params, prefix) { return handler.linePosAbsolute(params); }; +csiStateHandler['e'] = function (handler, params, prefix) { return handler.VPositionRelative(params); }; +csiStateHandler['f'] = function (handler, params, prefix) { return handler.HVPosition(params); }; +csiStateHandler['g'] = function (handler, params, prefix) { return handler.tabClear(params); }; +csiStateHandler['h'] = function (handler, params, prefix) { return handler.setMode(params); }; +csiStateHandler['l'] = function (handler, params, prefix) { return handler.resetMode(params); }; +csiStateHandler['m'] = function (handler, params, prefix) { return handler.charAttributes(params); }; +csiStateHandler['n'] = function (handler, params, prefix) { return handler.deviceStatus(params); }; +csiStateHandler['p'] = function (handler, params, prefix) { + switch (prefix) { + case '!': + handler.softReset(params); + break; + } +}; +csiStateHandler['q'] = function (handler, params, prefix, postfix) { + if (postfix === ' ') { + handler.setCursorStyle(params); + } +}; +csiStateHandler['r'] = function (handler, params) { return handler.setScrollRegion(params); }; +csiStateHandler['s'] = function (handler, params) { return handler.saveCursor(params); }; +csiStateHandler['u'] = function (handler, params) { return handler.restoreCursor(params); }; +csiStateHandler[EscapeSequences_1.C0.CAN] = function (handler, params, prefix, postfix, parser) { return parser.setState(ParserState.NORMAL); }; +var ParserState; +(function (ParserState) { + ParserState[ParserState["NORMAL"] = 0] = "NORMAL"; + ParserState[ParserState["ESCAPED"] = 1] = "ESCAPED"; + ParserState[ParserState["CSI_PARAM"] = 2] = "CSI_PARAM"; + ParserState[ParserState["CSI"] = 3] = "CSI"; + ParserState[ParserState["OSC"] = 4] = "OSC"; + ParserState[ParserState["CHARSET"] = 5] = "CHARSET"; + ParserState[ParserState["DCS"] = 6] = "DCS"; + ParserState[ParserState["IGNORE"] = 7] = "IGNORE"; +})(ParserState = exports.ParserState || (exports.ParserState = {})); +var Parser = (function () { + function Parser(_inputHandler, _terminal) { + this._inputHandler = _inputHandler; + this._terminal = _terminal; + this._state = ParserState.NORMAL; + } + Parser.prototype.parse = function (data) { + var l = data.length; + var j; + var cs; + var ch; + var code; + var low; + var cursorStartX = this._terminal.buffer.x; + var cursorStartY = this._terminal.buffer.y; + if (this._terminal.debug) { + this._terminal.log('data: ' + data); + } + this._position = 0; + if (this._terminal.surrogate_high) { + data = this._terminal.surrogate_high + data; + this._terminal.surrogate_high = ''; + } + for (; this._position < l; this._position++) { + ch = data[this._position]; + code = data.charCodeAt(this._position); + if (0xD800 <= code && code <= 0xDBFF) { + low = data.charCodeAt(this._position + 1); + if (isNaN(low)) { + this._terminal.surrogate_high = ch; + continue; + } + code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000; + ch += data.charAt(this._position + 1); + } + if (0xDC00 <= code && code <= 0xDFFF) + continue; + switch (this._state) { + case ParserState.NORMAL: + if (ch in normalStateHandler) { + normalStateHandler[ch](this, this._inputHandler); + } + else { + this._inputHandler.addChar(ch, code); + } + break; + case ParserState.ESCAPED: + if (ch in escapedStateHandler) { + escapedStateHandler[ch](this, this._terminal); + break; + } + switch (ch) { + case '(': + case ')': + case '*': + case '+': + case '-': + case '.': + switch (ch) { + case '(': + this._terminal.gcharset = 0; + break; + case ')': + this._terminal.gcharset = 1; + break; + case '*': + this._terminal.gcharset = 2; + break; + case '+': + this._terminal.gcharset = 3; + break; + case '-': + this._terminal.gcharset = 1; + break; + case '.': + this._terminal.gcharset = 2; + break; + } + this._state = ParserState.CHARSET; + break; + case '/': + this._terminal.gcharset = 3; + this._state = ParserState.CHARSET; + this._position--; + break; + case 'N': + this._state = ParserState.NORMAL; + break; + case 'O': + this._state = ParserState.NORMAL; + break; + case 'n': + this._terminal.setgLevel(2); + this._state = ParserState.NORMAL; + break; + case 'o': + this._terminal.setgLevel(3); + this._state = ParserState.NORMAL; + break; + case '|': + this._terminal.setgLevel(3); + this._state = ParserState.NORMAL; + break; + case '}': + this._terminal.setgLevel(2); + this._state = ParserState.NORMAL; + break; + case '~': + this._terminal.setgLevel(1); + this._state = ParserState.NORMAL; + break; + case '7': + this._inputHandler.saveCursor(); + this._state = ParserState.NORMAL; + break; + case '8': + this._inputHandler.restoreCursor(); + this._state = ParserState.NORMAL; + break; + case '#': + this._state = ParserState.NORMAL; + this._position++; + break; + case 'H': + this._terminal.tabSet(); + this._state = ParserState.NORMAL; + break; + case '=': + this._terminal.log('Serial port requested application keypad.'); + this._terminal.applicationKeypad = true; + if (this._terminal.viewport) { + this._terminal.viewport.syncScrollArea(); + } + this._state = ParserState.NORMAL; + break; + case '>': + this._terminal.log('Switching back to normal keypad.'); + this._terminal.applicationKeypad = false; + if (this._terminal.viewport) { + this._terminal.viewport.syncScrollArea(); + } + this._state = ParserState.NORMAL; + break; + default: + this._state = ParserState.NORMAL; + this._terminal.error('Unknown ESC control: %s.', ch); + break; + } + break; + case ParserState.CHARSET: + if (ch in Charsets_1.CHARSETS) { + cs = Charsets_1.CHARSETS[ch]; + if (ch === '/') { + this.skipNextChar(); + } + } + else { + cs = Charsets_1.DEFAULT_CHARSET; + } + this._terminal.setgCharset(this._terminal.gcharset, cs); + this._terminal.gcharset = null; + this._state = ParserState.NORMAL; + break; + case ParserState.OSC: + if (ch === EscapeSequences_1.C0.ESC || ch === EscapeSequences_1.C0.BEL) { + if (ch === EscapeSequences_1.C0.ESC) + this._position++; + this._terminal.params.push(this._terminal.currentParam); + switch (this._terminal.params[0]) { + case 0: + case 1: + case 2: + if (this._terminal.params[1]) { + this._terminal.title = this._terminal.params[1]; + this._terminal.handleTitle(this._terminal.title); + } + break; + case 3: + break; + case 4: + case 5: + break; + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + break; + case 46: + break; + case 50: + break; + case 51: + break; + case 52: + break; + case 104: + case 105: + case 110: + case 111: + case 112: + case 113: + case 114: + case 115: + case 116: + case 117: + case 118: + break; + } + this._terminal.params = []; + this._terminal.currentParam = 0; + this._state = ParserState.NORMAL; + } + else { + if (!this._terminal.params.length) { + if (ch >= '0' && ch <= '9') { + this._terminal.currentParam = + this._terminal.currentParam * 10 + ch.charCodeAt(0) - 48; + } + else if (ch === ';') { + this._terminal.params.push(this._terminal.currentParam); + this._terminal.currentParam = ''; + } + } + else { + this._terminal.currentParam += ch; + } + } + break; + case ParserState.CSI_PARAM: + if (ch in csiParamStateHandler) { + csiParamStateHandler[ch](this); + break; + } + this.finalizeParam(); + this._state = ParserState.CSI; + case ParserState.CSI: + if (ch in csiStateHandler) { + if (this._terminal.debug) { + this._terminal.log("CSI " + (this._terminal.prefix ? this._terminal.prefix : '') + " " + (this._terminal.params ? this._terminal.params.join(';') : '') + " " + (this._terminal.postfix ? this._terminal.postfix : '') + " " + ch); + } + csiStateHandler[ch](this._inputHandler, this._terminal.params, this._terminal.prefix, this._terminal.postfix, this); + } + else { + this._terminal.error('Unknown CSI code: %s.', ch); + } + this._state = ParserState.NORMAL; + this._terminal.prefix = ''; + this._terminal.postfix = ''; + break; + case ParserState.DCS: + if (ch === EscapeSequences_1.C0.ESC || ch === EscapeSequences_1.C0.BEL) { + if (ch === EscapeSequences_1.C0.ESC) + this._position++; + var pt = void 0; + var valid = void 0; + switch (this._terminal.prefix) { + case '': + break; + case '$q': + pt = this._terminal.currentParam; + valid = false; + switch (pt) { + case '"q': + pt = '0"q'; + break; + case '"p': + pt = '61"p'; + break; + case 'r': + pt = '' + + (this._terminal.buffer.scrollTop + 1) + + ';' + + (this._terminal.buffer.scrollBottom + 1) + + 'r'; + break; + case 'm': + pt = '0m'; + break; + default: + this._terminal.error('Unknown DCS Pt: %s.', pt); + pt = ''; + break; + } + this._terminal.send(EscapeSequences_1.C0.ESC + 'P' + +valid + '$r' + pt + EscapeSequences_1.C0.ESC + '\\'); + break; + case '+p': + break; + case '+q': + pt = this._terminal.currentParam; + valid = false; + this._terminal.send(EscapeSequences_1.C0.ESC + 'P' + +valid + '+r' + pt + EscapeSequences_1.C0.ESC + '\\'); + break; + default: + this._terminal.error('Unknown DCS prefix: %s.', this._terminal.prefix); + break; + } + this._terminal.currentParam = 0; + this._terminal.prefix = ''; + this._state = ParserState.NORMAL; + } + else if (!this._terminal.currentParam) { + if (!this._terminal.prefix && ch !== '$' && ch !== '+') { + this._terminal.currentParam = ch; + } + else if (this._terminal.prefix.length === 2) { + this._terminal.currentParam = ch; + } + else { + this._terminal.prefix += ch; + } + } + else { + this._terminal.currentParam += ch; + } + break; + case ParserState.IGNORE: + if (ch === EscapeSequences_1.C0.ESC || ch === EscapeSequences_1.C0.BEL) { + if (ch === EscapeSequences_1.C0.ESC) + this._position++; + this._state = ParserState.NORMAL; + } + break; + } + } + if (this._terminal.buffer.x !== cursorStartX || this._terminal.buffer.y !== cursorStartY) { + this._terminal.emit('cursormove'); + } + return this._state; + }; + Parser.prototype.setState = function (state) { + this._state = state; + }; + Parser.prototype.setPrefix = function (prefix) { + this._terminal.prefix = prefix; + }; + Parser.prototype.setPostfix = function (postfix) { + this._terminal.postfix = postfix; + }; + Parser.prototype.setParam = function (param) { + this._terminal.currentParam = param; + }; + Parser.prototype.getParam = function () { + return this._terminal.currentParam; + }; + Parser.prototype.finalizeParam = function () { + this._terminal.params.push(this._terminal.currentParam); + this._terminal.currentParam = 0; + }; + Parser.prototype.skipNextChar = function () { + this._position++; + }; + return Parser; +}()); +exports.Parser = Parser; + + + +},{"./Charsets":4,"./EscapeSequences":6}],11:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var MouseHelper_1 = require("./utils/MouseHelper"); +var Browser = require("./utils/Browser"); +var EventEmitter_1 = require("./EventEmitter"); +var SelectionModel_1 = require("./SelectionModel"); +var Buffer_1 = require("./Buffer"); +var DRAG_SCROLL_MAX_THRESHOLD = 50; +var DRAG_SCROLL_MAX_SPEED = 15; +var DRAG_SCROLL_INTERVAL = 50; +var WORD_SEPARATORS = ' ()[]{}\'"'; +var NON_BREAKING_SPACE_CHAR = String.fromCharCode(160); +var ALL_NON_BREAKING_SPACE_REGEX = new RegExp(NON_BREAKING_SPACE_CHAR, 'g'); +var SelectionMode; +(function (SelectionMode) { + SelectionMode[SelectionMode["NORMAL"] = 0] = "NORMAL"; + SelectionMode[SelectionMode["WORD"] = 1] = "WORD"; + SelectionMode[SelectionMode["LINE"] = 2] = "LINE"; +})(SelectionMode || (SelectionMode = {})); +var SelectionManager = (function (_super) { + __extends(SelectionManager, _super); + function SelectionManager(_terminal, _buffer, _charMeasure) { + var _this = _super.call(this) || this; + _this._terminal = _terminal; + _this._buffer = _buffer; + _this._charMeasure = _charMeasure; + _this._enabled = true; + _this._initListeners(); + _this.enable(); + _this._model = new SelectionModel_1.SelectionModel(_terminal); + _this._activeSelectionMode = SelectionMode.NORMAL; + return _this; + } + SelectionManager.prototype._initListeners = function () { + var _this = this; + this._mouseMoveListener = function (event) { return _this._onMouseMove(event); }; + this._mouseUpListener = function (event) { return _this._onMouseUp(event); }; + this._buffer.lines.on('trim', function (amount) { return _this._onTrim(amount); }); + }; + SelectionManager.prototype.disable = function () { + this.clearSelection(); + this._enabled = false; + }; + SelectionManager.prototype.enable = function () { + this._enabled = true; + }; + SelectionManager.prototype.setBuffer = function (buffer) { + this._buffer = buffer; + this.clearSelection(); + }; + Object.defineProperty(SelectionManager.prototype, "selectionStart", { + get: function () { return this._model.finalSelectionStart; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SelectionManager.prototype, "selectionEnd", { + get: function () { return this._model.finalSelectionEnd; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SelectionManager.prototype, "hasSelection", { + get: function () { + var start = this._model.finalSelectionStart; + var end = this._model.finalSelectionEnd; + if (!start || !end) { + return false; + } + return start[0] !== end[0] || start[1] !== end[1]; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SelectionManager.prototype, "selectionText", { + get: function () { + var start = this._model.finalSelectionStart; + var end = this._model.finalSelectionEnd; + if (!start || !end) { + return ''; + } + var startRowEndCol = start[1] === end[1] ? end[0] : null; + var result = []; + result.push(this._buffer.translateBufferLineToString(start[1], true, start[0], startRowEndCol)); + for (var i = start[1] + 1; i <= end[1] - 1; i++) { + var bufferLine = this._buffer.lines.get(i); + var lineText = this._buffer.translateBufferLineToString(i, true); + if (bufferLine.isWrapped) { + result[result.length - 1] += lineText; + } + else { + result.push(lineText); + } + } + if (start[1] !== end[1]) { + var bufferLine = this._buffer.lines.get(end[1]); + var lineText = this._buffer.translateBufferLineToString(end[1], true, 0, end[0]); + if (bufferLine.isWrapped) { + result[result.length - 1] += lineText; + } + else { + result.push(lineText); + } + } + var formattedResult = result.map(function (line) { + return line.replace(ALL_NON_BREAKING_SPACE_REGEX, ' '); + }).join(Browser.isMSWindows ? '\r\n' : '\n'); + return formattedResult; + }, + enumerable: true, + configurable: true + }); + SelectionManager.prototype.clearSelection = function () { + this._model.clearSelection(); + this._removeMouseDownListeners(); + this.refresh(); + }; + SelectionManager.prototype.refresh = function (isNewSelection) { + var _this = this; + if (!this._refreshAnimationFrame) { + this._refreshAnimationFrame = window.requestAnimationFrame(function () { return _this._refresh(); }); + } + if (Browser.isLinux && isNewSelection) { + var selectionText = this.selectionText; + if (selectionText.length) { + this.emit('newselection', this.selectionText); + } + } + }; + SelectionManager.prototype._refresh = function () { + this._refreshAnimationFrame = null; + this.emit('refresh', { start: this._model.finalSelectionStart, end: this._model.finalSelectionEnd }); + }; + SelectionManager.prototype.selectAll = function () { + this._model.isSelectAllActive = true; + this.refresh(); + this._terminal.emit('selection'); + }; + SelectionManager.prototype._onTrim = function (amount) { + var needsRefresh = this._model.onTrim(amount); + if (needsRefresh) { + this.refresh(); + } + }; + SelectionManager.prototype._getMouseBufferCoords = function (event) { + var coords = this._terminal.mouseHelper.getCoords(event, this._terminal.element, this._charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows, true); + if (!coords) { + return null; + } + coords[0]--; + coords[1]--; + coords[1] += this._terminal.buffer.ydisp; + return coords; + }; + SelectionManager.prototype._getMouseEventScrollAmount = function (event) { + var offset = MouseHelper_1.MouseHelper.getCoordsRelativeToElement(event, this._terminal.element)[1]; + var terminalHeight = this._terminal.rows * Math.ceil(this._charMeasure.height * this._terminal.options.lineHeight); + if (offset >= 0 && offset <= terminalHeight) { + return 0; + } + if (offset > terminalHeight) { + offset -= terminalHeight; + } + offset = Math.min(Math.max(offset, -DRAG_SCROLL_MAX_THRESHOLD), DRAG_SCROLL_MAX_THRESHOLD); + offset /= DRAG_SCROLL_MAX_THRESHOLD; + return (offset / Math.abs(offset)) + Math.round(offset * (DRAG_SCROLL_MAX_SPEED - 1)); + }; + SelectionManager.prototype.shouldForceSelection = function (event) { + return Browser.isMac ? event.altKey : event.shiftKey; + }; + SelectionManager.prototype.onMouseDown = function (event) { + if (event.button === 2 && this.hasSelection) { + return; + } + if (event.button !== 0) { + return; + } + if (!this._enabled) { + if (!this.shouldForceSelection(event)) { + return; + } + event.stopPropagation(); + } + event.preventDefault(); + this._dragScrollAmount = 0; + if (this._enabled && event.shiftKey) { + this._onIncrementalClick(event); + } + else { + if (event.detail === 1) { + this._onSingleClick(event); + } + else if (event.detail === 2) { + this._onDoubleClick(event); + } + else if (event.detail === 3) { + this._onTripleClick(event); + } + } + this._addMouseDownListeners(); + this.refresh(true); + }; + SelectionManager.prototype._addMouseDownListeners = function () { + var _this = this; + this._terminal.element.ownerDocument.addEventListener('mousemove', this._mouseMoveListener); + this._terminal.element.ownerDocument.addEventListener('mouseup', this._mouseUpListener); + this._dragScrollIntervalTimer = setInterval(function () { return _this._dragScroll(); }, DRAG_SCROLL_INTERVAL); + }; + SelectionManager.prototype._removeMouseDownListeners = function () { + this._terminal.element.ownerDocument.removeEventListener('mousemove', this._mouseMoveListener); + this._terminal.element.ownerDocument.removeEventListener('mouseup', this._mouseUpListener); + clearInterval(this._dragScrollIntervalTimer); + this._dragScrollIntervalTimer = null; + }; + SelectionManager.prototype._onIncrementalClick = function (event) { + if (this._model.selectionStart) { + this._model.selectionEnd = this._getMouseBufferCoords(event); + } + }; + SelectionManager.prototype._onSingleClick = function (event) { + this._model.selectionStartLength = 0; + this._model.isSelectAllActive = false; + this._activeSelectionMode = SelectionMode.NORMAL; + this._model.selectionStart = this._getMouseBufferCoords(event); + if (!this._model.selectionStart) { + return; + } + this._model.selectionEnd = null; + var line = this._buffer.lines.get(this._model.selectionStart[1]); + if (!line) { + return; + } + if (line.length >= this._model.selectionStart[0]) { + return; + } + var char = line[this._model.selectionStart[0]]; + if (char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) { + this._model.selectionStart[0]++; + } + }; + SelectionManager.prototype._onDoubleClick = function (event) { + var coords = this._getMouseBufferCoords(event); + if (coords) { + this._activeSelectionMode = SelectionMode.WORD; + this._selectWordAt(coords); + } + }; + SelectionManager.prototype._onTripleClick = function (event) { + var coords = this._getMouseBufferCoords(event); + if (coords) { + this._activeSelectionMode = SelectionMode.LINE; + this._selectLineAt(coords[1]); + } + }; + SelectionManager.prototype._onMouseMove = function (event) { + event.stopImmediatePropagation(); + var previousSelectionEnd = this._model.selectionEnd ? [this._model.selectionEnd[0], this._model.selectionEnd[1]] : null; + this._model.selectionEnd = this._getMouseBufferCoords(event); + if (!this._model.selectionEnd) { + this.refresh(true); + return; + } + if (this._activeSelectionMode === SelectionMode.LINE) { + if (this._model.selectionEnd[1] < this._model.selectionStart[1]) { + this._model.selectionEnd[0] = 0; + } + else { + this._model.selectionEnd[0] = this._terminal.cols; + } + } + else if (this._activeSelectionMode === SelectionMode.WORD) { + this._selectToWordAt(this._model.selectionEnd); + } + this._dragScrollAmount = this._getMouseEventScrollAmount(event); + if (this._dragScrollAmount > 0) { + this._model.selectionEnd[0] = this._terminal.cols; + } + else if (this._dragScrollAmount < 0) { + this._model.selectionEnd[0] = 0; + } + if (this._model.selectionEnd[1] < this._buffer.lines.length) { + var char = this._buffer.lines.get(this._model.selectionEnd[1])[this._model.selectionEnd[0]]; + if (char && char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) { + this._model.selectionEnd[0]++; + } + } + if (!previousSelectionEnd || + previousSelectionEnd[0] !== this._model.selectionEnd[0] || + previousSelectionEnd[1] !== this._model.selectionEnd[1]) { + this.refresh(true); + } + }; + SelectionManager.prototype._dragScroll = function () { + if (this._dragScrollAmount) { + this._terminal.scrollLines(this._dragScrollAmount, false); + if (this._dragScrollAmount > 0) { + this._model.selectionEnd = [this._terminal.cols - 1, Math.min(this._terminal.buffer.ydisp + this._terminal.rows, this._terminal.buffer.lines.length - 1)]; + } + else { + this._model.selectionEnd = [0, this._terminal.buffer.ydisp]; + } + this.refresh(); + } + }; + SelectionManager.prototype._onMouseUp = function (event) { + this._removeMouseDownListeners(); + if (this.hasSelection) + this._terminal.emit('selection'); + }; + SelectionManager.prototype._convertViewportColToCharacterIndex = function (bufferLine, coords) { + var charIndex = coords[0]; + for (var i = 0; coords[0] >= i; i++) { + var char = bufferLine[i]; + if (char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) { + charIndex--; + } + else if (char[Buffer_1.CHAR_DATA_CHAR_INDEX].length > 1 && coords[0] !== i) { + charIndex += char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + } + } + return charIndex; + }; + SelectionManager.prototype.setSelection = function (col, row, length) { + this._model.clearSelection(); + this._removeMouseDownListeners(); + this._model.selectionStart = [col, row]; + this._model.selectionStartLength = length; + this.refresh(); + }; + SelectionManager.prototype._getWordAt = function (coords) { + var bufferLine = this._buffer.lines.get(coords[1]); + if (!bufferLine) { + return null; + } + var line = this._buffer.translateBufferLineToString(coords[1], false); + var startIndex = this._convertViewportColToCharacterIndex(bufferLine, coords); + var endIndex = startIndex; + var charOffset = coords[0] - startIndex; + var leftWideCharCount = 0; + var rightWideCharCount = 0; + var leftLongCharOffset = 0; + var rightLongCharOffset = 0; + if (line.charAt(startIndex) === ' ') { + while (startIndex > 0 && line.charAt(startIndex - 1) === ' ') { + startIndex--; + } + while (endIndex < line.length && line.charAt(endIndex + 1) === ' ') { + endIndex++; + } + } + else { + var startCol = coords[0]; + var endCol = coords[0]; + if (bufferLine[startCol][Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) { + leftWideCharCount++; + startCol--; + } + if (bufferLine[endCol][Buffer_1.CHAR_DATA_WIDTH_INDEX] === 2) { + rightWideCharCount++; + endCol++; + } + if (bufferLine[endCol][Buffer_1.CHAR_DATA_CHAR_INDEX].length > 1) { + rightLongCharOffset += bufferLine[endCol][Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + endIndex += bufferLine[endCol][Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + } + while (startCol > 0 && startIndex > 0 && !this._isCharWordSeparator(bufferLine[startCol - 1])) { + var char = bufferLine[startCol - 1]; + if (char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) { + leftWideCharCount++; + startCol--; + } + else if (char[Buffer_1.CHAR_DATA_CHAR_INDEX].length > 1) { + leftLongCharOffset += char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + startIndex -= char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + } + startIndex--; + startCol--; + } + while (endCol < bufferLine.length && endIndex + 1 < line.length && !this._isCharWordSeparator(bufferLine[endCol + 1])) { + var char = bufferLine[endCol + 1]; + if (char[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 2) { + rightWideCharCount++; + endCol++; + } + else if (char[Buffer_1.CHAR_DATA_CHAR_INDEX].length > 1) { + rightLongCharOffset += char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + endIndex += char[Buffer_1.CHAR_DATA_CHAR_INDEX].length - 1; + } + endIndex++; + endCol++; + } + } + endIndex++; + var start = startIndex + + charOffset + - leftWideCharCount + + leftLongCharOffset; + var length = Math.min(this._terminal.cols, endIndex + - startIndex + + leftWideCharCount + + rightWideCharCount + - leftLongCharOffset + - rightLongCharOffset); + return { start: start, length: length }; + }; + SelectionManager.prototype._selectWordAt = function (coords) { + var wordPosition = this._getWordAt(coords); + if (wordPosition) { + this._model.selectionStart = [wordPosition.start, coords[1]]; + this._model.selectionStartLength = wordPosition.length; + } + }; + SelectionManager.prototype._selectToWordAt = function (coords) { + var wordPosition = this._getWordAt(coords); + if (wordPosition) { + this._model.selectionEnd = [this._model.areSelectionValuesReversed() ? wordPosition.start : (wordPosition.start + wordPosition.length), coords[1]]; + } + }; + SelectionManager.prototype._isCharWordSeparator = function (charData) { + if (charData[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 0) { + return false; + } + return WORD_SEPARATORS.indexOf(charData[Buffer_1.CHAR_DATA_CHAR_INDEX]) >= 0; + }; + SelectionManager.prototype._selectLineAt = function (line) { + this._model.selectionStart = [0, line]; + this._model.selectionStartLength = this._terminal.cols; + }; + return SelectionManager; +}(EventEmitter_1.EventEmitter)); +exports.SelectionManager = SelectionManager; + + + +},{"./Buffer":1,"./EventEmitter":7,"./SelectionModel":12,"./utils/Browser":28,"./utils/MouseHelper":32}],12:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var SelectionModel = (function () { + function SelectionModel(_terminal) { + this._terminal = _terminal; + this.clearSelection(); + } + SelectionModel.prototype.clearSelection = function () { + this.selectionStart = null; + this.selectionEnd = null; + this.isSelectAllActive = false; + this.selectionStartLength = 0; + }; + Object.defineProperty(SelectionModel.prototype, "finalSelectionStart", { + get: function () { + if (this.isSelectAllActive) { + return [0, 0]; + } + if (!this.selectionEnd || !this.selectionStart) { + return this.selectionStart; + } + return this.areSelectionValuesReversed() ? this.selectionEnd : this.selectionStart; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SelectionModel.prototype, "finalSelectionEnd", { + get: function () { + if (this.isSelectAllActive) { + return [this._terminal.cols, this._terminal.buffer.ybase + this._terminal.rows - 1]; + } + if (!this.selectionStart) { + return null; + } + if (!this.selectionEnd || this.areSelectionValuesReversed()) { + return [this.selectionStart[0] + this.selectionStartLength, this.selectionStart[1]]; + } + if (this.selectionStartLength) { + if (this.selectionEnd[1] === this.selectionStart[1]) { + return [Math.max(this.selectionStart[0] + this.selectionStartLength, this.selectionEnd[0]), this.selectionEnd[1]]; + } + } + return this.selectionEnd; + }, + enumerable: true, + configurable: true + }); + SelectionModel.prototype.areSelectionValuesReversed = function () { + var start = this.selectionStart; + var end = this.selectionEnd; + if (!start || !end) { + return false; + } + return start[1] > end[1] || (start[1] === end[1] && start[0] > end[0]); + }; + SelectionModel.prototype.onTrim = function (amount) { + if (this.selectionStart) { + this.selectionStart[1] -= amount; + } + if (this.selectionEnd) { + this.selectionEnd[1] -= amount; + } + if (this.selectionEnd && this.selectionEnd[1] < 0) { + this.clearSelection(); + return true; + } + if (this.selectionStart && this.selectionStart[1] < 0) { + this.selectionStart[1] = 0; + } + return false; + }; + return SelectionModel; +}()); +exports.SelectionModel = SelectionModel; + + + +},{}],13:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var BufferSet_1 = require("./BufferSet"); +var Buffer_1 = require("./Buffer"); +var CompositionHelper_1 = require("./CompositionHelper"); +var EventEmitter_1 = require("./EventEmitter"); +var Viewport_1 = require("./Viewport"); +var Clipboard_1 = require("./handlers/Clipboard"); +var EscapeSequences_1 = require("./EscapeSequences"); +var InputHandler_1 = require("./InputHandler"); +var Parser_1 = require("./Parser"); +var Renderer_1 = require("./renderer/Renderer"); +var Linkifier_1 = require("./Linkifier"); +var SelectionManager_1 = require("./SelectionManager"); +var CharMeasure_1 = require("./utils/CharMeasure"); +var Browser = require("./utils/Browser"); +var MouseHelper_1 = require("./utils/MouseHelper"); +var Sounds_1 = require("./utils/Sounds"); +var ColorManager_1 = require("./renderer/ColorManager"); +var MouseZoneManager_1 = require("./input/MouseZoneManager"); +var CharAtlas_1 = require("./renderer/CharAtlas"); +var document = (typeof window !== 'undefined') ? window.document : null; +var WRITE_BUFFER_PAUSE_THRESHOLD = 5; +var WRITE_BATCH_SIZE = 300; +var DEFAULT_OPTIONS = { + cols: 80, + rows: 24, + convertEol: false, + termName: 'xterm', + cursorBlink: false, + cursorStyle: 'block', + bellSound: Sounds_1.BellSound, + bellStyle: 'none', + enableBold: true, + fontFamily: 'courier-new, courier, monospace', + fontSize: 15, + lineHeight: 1.0, + letterSpacing: 0, + scrollback: 1000, + screenKeys: false, + debug: false, + cancelEvents: false, + disableStdin: false, + useFlowControl: false, + allowTransparency: false, + tabStopWidth: 8, + theme: null +}; +var Terminal = (function (_super) { + __extends(Terminal, _super); + function Terminal(options) { + if (options === void 0) { options = {}; } + var _this = _super.call(this) || this; + _this.browser = Browser; + _this.options = options; + _this.setup(); + return _this; + } + Terminal.prototype.setup = function () { + var _this = this; + Object.keys(DEFAULT_OPTIONS).forEach(function (key) { + if (_this.options[key] == null) { + _this.options[key] = DEFAULT_OPTIONS[key]; + } + _this[key] = _this.options[key]; + }); + this.parent = document ? document.body : null; + this.cols = this.options.cols; + this.rows = this.options.rows; + if (this.options.handler) { + this.on('data', this.options.handler); + } + this.cursorState = 0; + this.cursorHidden = false; + this.sendDataQueue = ''; + this.customKeyEventHandler = null; + this.applicationKeypad = false; + this.applicationCursor = false; + this.originMode = false; + this.insertMode = false; + this.wraparoundMode = true; + this.bracketedPasteMode = false; + this.charset = null; + this.gcharset = null; + this.glevel = 0; + this.charsets = [null]; + this.readable = true; + this.writable = true; + this.defAttr = (0 << 18) | (257 << 9) | (256 << 0); + this.curAttr = (0 << 18) | (257 << 9) | (256 << 0); + this.params = []; + this.currentParam = 0; + this.prefix = ''; + this.postfix = ''; + this.writeBuffer = []; + this.writeInProgress = false; + this.xoffSentToCatchUp = false; + this.writeStopped = false; + this.surrogate_high = ''; + this.userScrolling = false; + this.inputHandler = new InputHandler_1.InputHandler(this); + this.parser = new Parser_1.Parser(this.inputHandler, this); + this.renderer = this.renderer || null; + this.selectionManager = this.selectionManager || null; + this.linkifier = this.linkifier || new Linkifier_1.Linkifier(this); + this._mouseZoneManager = this._mouseZoneManager || null; + this.buffers = new BufferSet_1.BufferSet(this); + this.buffer = this.buffers.active; + this.buffers.on('activate', function (buffer) { + _this.buffer = buffer; + }); + if (this.selectionManager) { + this.selectionManager.setBuffer(this.buffer); + } + }; + Terminal.prototype.eraseAttr = function () { + return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff); + }; + Terminal.prototype.focus = function () { + if (this.textarea) { + this.textarea.focus(); + } + }; + Object.defineProperty(Terminal.prototype, "isFocused", { + get: function () { + return document.activeElement === this.textarea; + }, + enumerable: true, + configurable: true + }); + Terminal.prototype.getOption = function (key) { + if (!(key in DEFAULT_OPTIONS)) { + throw new Error('No option with key "' + key + '"'); + } + if (typeof this.options[key] !== 'undefined') { + return this.options[key]; + } + return this[key]; + }; + Terminal.prototype.setOption = function (key, value) { + if (!(key in DEFAULT_OPTIONS)) { + throw new Error('No option with key "' + key + '"'); + } + switch (key) { + case 'bellStyle': + if (!value) { + value = 'none'; + } + break; + case 'cursorStyle': + if (!value) { + value = 'block'; + } + break; + case 'lineHeight': + if (value < 1) { + console.warn(key + " cannot be less than 1, value: " + value); + return; + } + case 'tabStopWidth': + if (value < 1) { + console.warn(key + " cannot be less than 1, value: " + value); + return; + } + break; + case 'theme': + if (this.renderer) { + this._setTheme(value); + return; + } + break; + case 'scrollback': + value = Math.min(value, Buffer_1.MAX_BUFFER_SIZE); + if (value < 0) { + console.warn(key + " cannot be less than 0, value: " + value); + return; + } + if (this.options[key] !== value) { + var newBufferLength = this.rows + value; + if (this.buffer.lines.length > newBufferLength) { + var amountToTrim = this.buffer.lines.length - newBufferLength; + var needsRefresh = (this.buffer.ydisp - amountToTrim < 0); + this.buffer.lines.trimStart(amountToTrim); + this.buffer.ybase = Math.max(this.buffer.ybase - amountToTrim, 0); + this.buffer.ydisp = Math.max(this.buffer.ydisp - amountToTrim, 0); + if (needsRefresh) { + this.refresh(0, this.rows - 1); + } + } + } + break; + } + this[key] = value; + this.options[key] = value; + switch (key) { + case 'fontFamily': + case 'fontSize': + this.renderer.clear(); + this.charMeasure.measure(this.options); + break; + case 'enableBold': + case 'letterSpacing': + case 'lineHeight': + this.renderer.clear(); + this.renderer.onResize(this.cols, this.rows, false); + this.refresh(0, this.rows - 1); + case 'scrollback': + this.buffers.resize(this.cols, this.rows); + this.viewport.syncScrollArea(); + break; + case 'tabStopWidth': + this.buffers.setupTabStops(); + break; + case 'bellSound': + case 'bellStyle': + this.syncBellSound(); + break; + } + if (this.renderer) { + this.renderer.onOptionsChanged(); + } + }; + Terminal.prototype._onTextAreaFocus = function () { + if (this.sendFocus) { + this.send(EscapeSequences_1.C0.ESC + '[I'); + } + this.element.classList.add('focus'); + this.showCursor(); + this.emit('focus'); + }; + ; + Terminal.prototype.blur = function () { + return this.textarea.blur(); + }; + Terminal.prototype._onTextAreaBlur = function () { + this.refresh(this.buffer.y, this.buffer.y); + if (this.sendFocus) { + this.send(EscapeSequences_1.C0.ESC + '[O'); + } + this.element.classList.remove('focus'); + this.emit('blur'); + }; + Terminal.prototype.initGlobal = function () { + var _this = this; + this.bindKeys(); + on(this.element, 'copy', function (event) { + if (!_this.hasSelection()) { + return; + } + Clipboard_1.copyHandler(event, _this, _this.selectionManager); + }); + var pasteHandlerWrapper = function (event) { return Clipboard_1.pasteHandler(event, _this); }; + on(this.textarea, 'paste', pasteHandlerWrapper); + on(this.element, 'paste', pasteHandlerWrapper); + if (Browser.isFirefox) { + on(this.element, 'mousedown', function (event) { + if (event.button === 2) { + Clipboard_1.rightClickHandler(event, _this.textarea, _this.selectionManager); + } + }); + } + else { + on(this.element, 'contextmenu', function (event) { + Clipboard_1.rightClickHandler(event, _this.textarea, _this.selectionManager); + }); + } + if (Browser.isLinux) { + on(this.element, 'auxclick', function (event) { + if (event.button === 1) { + Clipboard_1.moveTextAreaUnderMouseCursor(event, _this.textarea); + } + }); + } + }; + Terminal.prototype.bindKeys = function () { + var _this = this; + var self = this; + on(this.element, 'keydown', function (ev) { + if (document.activeElement !== this) { + return; + } + self._keyDown(ev); + }, true); + on(this.element, 'keypress', function (ev) { + if (document.activeElement !== this) { + return; + } + self._keyPress(ev); + }, true); + on(this.element, 'keyup', function (ev) { + if (!wasMondifierKeyOnlyEvent(ev)) { + _this.focus(); + } + }, true); + on(this.textarea, 'keydown', function (ev) { + _this._keyDown(ev); + }, true); + on(this.textarea, 'keypress', function (ev) { + _this._keyPress(ev); + _this.textarea.value = ''; + }, true); + on(this.textarea, 'compositionstart', function () { return _this.compositionHelper.compositionstart(); }); + on(this.textarea, 'compositionupdate', function (e) { return _this.compositionHelper.compositionupdate(e); }); + on(this.textarea, 'compositionend', function () { return _this.compositionHelper.compositionend(); }); + this.on('refresh', function () { return _this.compositionHelper.updateCompositionElements(); }); + this.on('refresh', function (data) { return _this.queueLinkification(data.start, data.end); }); + }; + Terminal.prototype.open = function (parent) { + var _this = this; + var i = 0; + var div; + this.parent = parent || this.parent; + if (!this.parent) { + throw new Error('Terminal requires a parent element.'); + } + this.context = this.parent.ownerDocument.defaultView; + this.document = this.parent.ownerDocument; + this.body = this.document.body; + CharAtlas_1.initialize(this.document, this.options.allowTransparency); + this.element = this.document.createElement('div'); + this.element.classList.add('terminal'); + this.element.classList.add('xterm'); + this.element.setAttribute('tabindex', '0'); + this.parent.appendChild(this.element); + var fragment = document.createDocumentFragment(); + this.viewportElement = document.createElement('div'); + this.viewportElement.classList.add('xterm-viewport'); + fragment.appendChild(this.viewportElement); + this.viewportScrollArea = document.createElement('div'); + this.viewportScrollArea.classList.add('xterm-scroll-area'); + this.viewportElement.appendChild(this.viewportScrollArea); + this._mouseZoneManager = new MouseZoneManager_1.MouseZoneManager(this); + this.on('scroll', function () { return _this._mouseZoneManager.clearAll(); }); + this.linkifier.attachToDom(this._mouseZoneManager); + this.helperContainer = document.createElement('div'); + this.helperContainer.classList.add('xterm-helpers'); + fragment.appendChild(this.helperContainer); + this.textarea = document.createElement('textarea'); + this.textarea.classList.add('xterm-helper-textarea'); + this.textarea.setAttribute('autocorrect', 'off'); + this.textarea.setAttribute('autocapitalize', 'off'); + this.textarea.setAttribute('spellcheck', 'false'); + this.textarea.tabIndex = 0; + this.textarea.addEventListener('focus', function () { return _this._onTextAreaFocus(); }); + this.textarea.addEventListener('blur', function () { return _this._onTextAreaBlur(); }); + this.helperContainer.appendChild(this.textarea); + this.compositionView = document.createElement('div'); + this.compositionView.classList.add('composition-view'); + this.compositionHelper = new CompositionHelper_1.CompositionHelper(this.textarea, this.compositionView, this); + this.helperContainer.appendChild(this.compositionView); + this.charSizeStyleElement = document.createElement('style'); + this.helperContainer.appendChild(this.charSizeStyleElement); + this.charMeasure = new CharMeasure_1.CharMeasure(document, this.helperContainer); + this.syncBellSound(); + this.element.appendChild(fragment); + this.renderer = new Renderer_1.Renderer(this, this.options.theme); + this.options.theme = null; + this.viewport = new Viewport_1.Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure); + this.viewport.onThemeChanged(this.renderer.colorManager.colors); + this.on('cursormove', function () { return _this.renderer.onCursorMove(); }); + this.on('resize', function () { return _this.renderer.onResize(_this.cols, _this.rows, false); }); + this.on('blur', function () { return _this.renderer.onBlur(); }); + this.on('focus', function () { return _this.renderer.onFocus(); }); + this.charMeasure.on('charsizechanged', function () { return _this.renderer.onResize(_this.cols, _this.rows, true); }); + this.renderer.on('resize', function (dimensions) { return _this.viewport.syncScrollArea(); }); + this.selectionManager = new SelectionManager_1.SelectionManager(this, this.buffer, this.charMeasure); + this.element.addEventListener('mousedown', function (e) { return _this.selectionManager.onMouseDown(e); }); + this.selectionManager.on('refresh', function (data) { return _this.renderer.onSelectionChanged(data.start, data.end); }); + this.selectionManager.on('newselection', function (text) { + _this.textarea.value = text; + _this.textarea.focus(); + _this.textarea.select(); + }); + this.on('scroll', function () { + _this.viewport.syncScrollArea(); + _this.selectionManager.refresh(); + }); + this.viewportElement.addEventListener('scroll', function () { return _this.selectionManager.refresh(); }); + this.mouseHelper = new MouseHelper_1.MouseHelper(this.renderer); + this.charMeasure.measure(this.options); + this.refresh(0, this.rows - 1); + this.initGlobal(); + this.bindMouse(); + }; + Terminal.prototype._setTheme = function (theme) { + var colors = this.renderer.setTheme(theme); + if (this.viewport) { + this.viewport.onThemeChanged(colors); + } + }; + Terminal.applyAddon = function (addon) { + addon.apply(Terminal); + }; + Terminal.prototype.bindMouse = function () { + var _this = this; + var el = this.element; + var self = this; + var pressed = 32; + function sendButton(ev) { + var button; + var pos; + button = getButton(ev); + pos = self.mouseHelper.getRawByteCoords(ev, self.element, self.charMeasure, self.options.lineHeight, self.cols, self.rows); + if (!pos) + return; + sendEvent(button, pos); + switch (ev.overrideType || ev.type) { + case 'mousedown': + pressed = button; + break; + case 'mouseup': + pressed = 32; + break; + case 'wheel': + break; + } + } + function sendMove(ev) { + var button = pressed; + var pos = self.mouseHelper.getRawByteCoords(ev, self.element, self.charMeasure, self.options.lineHeight, self.cols, self.rows); + if (!pos) + return; + button += 32; + sendEvent(button, pos); + } + function encode(data, ch) { + if (!self.utfMouse) { + if (ch === 255) { + data.push(0); + return; + } + if (ch > 127) + ch = 127; + data.push(ch); + } + else { + if (ch === 2047) { + data.push(0); + return; + } + if (ch < 127) { + data.push(ch); + } + else { + if (ch > 2047) + ch = 2047; + data.push(0xC0 | (ch >> 6)); + data.push(0x80 | (ch & 0x3F)); + } + } + } + function sendEvent(button, pos) { + if (self.vt300Mouse) { + button &= 3; + pos.x -= 32; + pos.y -= 32; + var data_1 = EscapeSequences_1.C0.ESC + '[24'; + if (button === 0) + data_1 += '1'; + else if (button === 1) + data_1 += '3'; + else if (button === 2) + data_1 += '5'; + else if (button === 3) + return; + else + data_1 += '0'; + data_1 += '~[' + pos.x + ',' + pos.y + ']\r'; + self.send(data_1); + return; + } + if (self.decLocator) { + button &= 3; + pos.x -= 32; + pos.y -= 32; + if (button === 0) + button = 2; + else if (button === 1) + button = 4; + else if (button === 2) + button = 6; + else if (button === 3) + button = 3; + self.send(EscapeSequences_1.C0.ESC + '[' + + button + + ';' + + (button === 3 ? 4 : 0) + + ';' + + pos.y + + ';' + + pos.x + + ';' + + pos.page || 0 + + '&w'); + return; + } + if (self.urxvtMouse) { + pos.x -= 32; + pos.y -= 32; + pos.x++; + pos.y++; + self.send(EscapeSequences_1.C0.ESC + '[' + button + ';' + pos.x + ';' + pos.y + 'M'); + return; + } + if (self.sgrMouse) { + pos.x -= 32; + pos.y -= 32; + self.send(EscapeSequences_1.C0.ESC + '[<' + + (((button & 3) === 3 ? button & ~3 : button) - 32) + + ';' + + pos.x + + ';' + + pos.y + + ((button & 3) === 3 ? 'm' : 'M')); + return; + } + var data = []; + encode(data, button); + encode(data, pos.x); + encode(data, pos.y); + self.send(EscapeSequences_1.C0.ESC + '[M' + String.fromCharCode.apply(String, data)); + } + function getButton(ev) { + var button; + var shift; + var meta; + var ctrl; + var mod; + switch (ev.overrideType || ev.type) { + case 'mousedown': + button = ev.button != null + ? +ev.button + : ev.which != null + ? ev.which - 1 + : null; + if (Browser.isMSIE) { + button = button === 1 ? 0 : button === 4 ? 1 : button; + } + break; + case 'mouseup': + button = 3; + break; + case 'DOMMouseScroll': + button = ev.detail < 0 + ? 64 + : 65; + break; + case 'wheel': + button = ev.wheelDeltaY > 0 + ? 64 + : 65; + break; + } + shift = ev.shiftKey ? 4 : 0; + meta = ev.metaKey ? 8 : 0; + ctrl = ev.ctrlKey ? 16 : 0; + mod = shift | meta | ctrl; + if (self.vt200Mouse) { + mod &= ctrl; + } + else if (!self.normalMouse) { + mod = 0; + } + button = (32 + (mod << 2)) + button; + return button; + } + on(el, 'mousedown', function (ev) { + ev.preventDefault(); + _this.focus(); + if (!_this.mouseEvents || _this.selectionManager.shouldForceSelection(ev)) { + return; + } + sendButton(ev); + if (_this.vt200Mouse) { + ev.overrideType = 'mouseup'; + sendButton(ev); + return _this.cancel(ev); + } + if (_this.normalMouse) + on(_this.document, 'mousemove', sendMove); + if (!_this.x10Mouse) { + var handler_1 = function (ev) { + sendButton(ev); + if (_this.normalMouse) + off(_this.document, 'mousemove', sendMove); + off(_this.document, 'mouseup', handler_1); + return _this.cancel(ev); + }; + on(_this.document, 'mouseup', handler_1); + } + return _this.cancel(ev); + }); + on(el, 'wheel', function (ev) { + if (!_this.mouseEvents) + return; + if (_this.x10Mouse || _this.vt300Mouse || _this.decLocator) + return; + sendButton(ev); + ev.preventDefault(); + }); + on(el, 'wheel', function (ev) { + if (_this.mouseEvents) + return; + _this.viewport.onWheel(ev); + return _this.cancel(ev); + }); + on(el, 'touchstart', function (ev) { + if (_this.mouseEvents) + return; + _this.viewport.onTouchStart(ev); + return _this.cancel(ev); + }); + on(el, 'touchmove', function (ev) { + if (_this.mouseEvents) + return; + _this.viewport.onTouchMove(ev); + return _this.cancel(ev); + }); + }; + Terminal.prototype.destroy = function () { + _super.prototype.destroy.call(this); + this.readable = false; + this.writable = false; + this.handler = function () { }; + this.write = function () { }; + if (this.element && this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + } + }; + Terminal.prototype.refresh = function (start, end) { + if (this.renderer) { + this.renderer.queueRefresh(start, end); + } + }; + Terminal.prototype.queueLinkification = function (start, end) { + if (this.linkifier) { + this.linkifier.linkifyRows(start, end); + } + }; + Terminal.prototype.showCursor = function () { + if (!this.cursorState) { + this.cursorState = 1; + this.refresh(this.buffer.y, this.buffer.y); + } + }; + Terminal.prototype.scroll = function (isWrapped) { + var newLine = this.blankLine(undefined, isWrapped); + var topRow = this.buffer.ybase + this.buffer.scrollTop; + var bottomRow = this.buffer.ybase + this.buffer.scrollBottom; + if (this.buffer.scrollTop === 0) { + var willBufferBeTrimmed = this.buffer.lines.length === this.buffer.lines.maxLength; + if (bottomRow === this.buffer.lines.length - 1) { + this.buffer.lines.push(newLine); + } + else { + this.buffer.lines.splice(bottomRow + 1, 0, newLine); + } + if (!willBufferBeTrimmed) { + this.buffer.ybase++; + if (!this.userScrolling) { + this.buffer.ydisp++; + } + } + else { + if (this.userScrolling) { + this.buffer.ydisp = Math.max(this.buffer.ydisp - 1, 0); + } + } + } + else { + var scrollRegionHeight = bottomRow - topRow + 1; + this.buffer.lines.shiftElements(topRow + 1, scrollRegionHeight - 1, -1); + this.buffer.lines.set(bottomRow, newLine); + } + if (!this.userScrolling) { + this.buffer.ydisp = this.buffer.ybase; + } + this.updateRange(this.buffer.scrollTop); + this.updateRange(this.buffer.scrollBottom); + this.emit('scroll', this.buffer.ydisp); + }; + Terminal.prototype.scrollLines = function (disp, suppressScrollEvent) { + if (disp < 0) { + if (this.buffer.ydisp === 0) { + return; + } + this.userScrolling = true; + } + else if (disp + this.buffer.ydisp >= this.buffer.ybase) { + this.userScrolling = false; + } + var oldYdisp = this.buffer.ydisp; + this.buffer.ydisp = Math.max(Math.min(this.buffer.ydisp + disp, this.buffer.ybase), 0); + if (oldYdisp === this.buffer.ydisp) { + return; + } + if (!suppressScrollEvent) { + this.emit('scroll', this.buffer.ydisp); + } + this.refresh(0, this.rows - 1); + }; + Terminal.prototype.scrollPages = function (pageCount) { + this.scrollLines(pageCount * (this.rows - 1)); + }; + Terminal.prototype.scrollToTop = function () { + this.scrollLines(-this.buffer.ydisp); + }; + Terminal.prototype.scrollToBottom = function () { + this.scrollLines(this.buffer.ybase - this.buffer.ydisp); + }; + Terminal.prototype.write = function (data) { + var _this = this; + this.writeBuffer.push(data); + if (this.options.useFlowControl && !this.xoffSentToCatchUp && this.writeBuffer.length >= WRITE_BUFFER_PAUSE_THRESHOLD) { + this.send(EscapeSequences_1.C0.DC3); + this.xoffSentToCatchUp = true; + } + if (!this.writeInProgress && this.writeBuffer.length > 0) { + this.writeInProgress = true; + setTimeout(function () { + _this.innerWrite(); + }); + } + }; + Terminal.prototype.innerWrite = function () { + var _this = this; + var writeBatch = this.writeBuffer.splice(0, WRITE_BATCH_SIZE); + while (writeBatch.length > 0) { + var data = writeBatch.shift(); + if (this.xoffSentToCatchUp && writeBatch.length === 0 && this.writeBuffer.length === 0) { + this.send(EscapeSequences_1.C0.DC1); + this.xoffSentToCatchUp = false; + } + this.refreshStart = this.buffer.y; + this.refreshEnd = this.buffer.y; + var state = this.parser.parse(data); + this.parser.setState(state); + this.updateRange(this.buffer.y); + this.refresh(this.refreshStart, this.refreshEnd); + } + if (this.writeBuffer.length > 0) { + setTimeout(function () { return _this.innerWrite(); }, 0); + } + else { + this.writeInProgress = false; + } + }; + Terminal.prototype.writeln = function (data) { + this.write(data + '\r\n'); + }; + Terminal.prototype.attachCustomKeyEventHandler = function (customKeyEventHandler) { + this.customKeyEventHandler = customKeyEventHandler; + }; + Terminal.prototype.setHypertextLinkHandler = function (handler) { + if (!this.linkifier) { + throw new Error('Cannot attach a hypertext link handler before Terminal.open is called'); + } + this.linkifier.setHypertextLinkHandler(handler); + this.refresh(0, this.rows - 1); + }; + Terminal.prototype.setHypertextValidationCallback = function (callback) { + if (!this.linkifier) { + throw new Error('Cannot attach a hypertext validation callback before Terminal.open is called'); + } + this.linkifier.setHypertextValidationCallback(callback); + this.refresh(0, this.rows - 1); + }; + Terminal.prototype.registerLinkMatcher = function (regex, handler, options) { + if (this.linkifier) { + var matcherId = this.linkifier.registerLinkMatcher(regex, handler, options); + this.refresh(0, this.rows - 1); + return matcherId; + } + return 0; + }; + Terminal.prototype.deregisterLinkMatcher = function (matcherId) { + if (this.linkifier) { + if (this.linkifier.deregisterLinkMatcher(matcherId)) { + this.refresh(0, this.rows - 1); + } + } + }; + Terminal.prototype.hasSelection = function () { + return this.selectionManager ? this.selectionManager.hasSelection : false; + }; + Terminal.prototype.getSelection = function () { + return this.selectionManager ? this.selectionManager.selectionText : ''; + }; + Terminal.prototype.clearSelection = function () { + if (this.selectionManager) { + this.selectionManager.clearSelection(); + } + }; + Terminal.prototype.selectAll = function () { + if (this.selectionManager) { + this.selectionManager.selectAll(); + } + }; + Terminal.prototype._keyDown = function (ev) { + if (this.customKeyEventHandler && this.customKeyEventHandler(ev) === false) { + return false; + } + if (!this.compositionHelper.keydown(ev)) { + if (this.buffer.ybase !== this.buffer.ydisp) { + this.scrollToBottom(); + } + return false; + } + var result = this._evaluateKeyEscapeSequence(ev); + if (result.key === EscapeSequences_1.C0.DC3) { + this.writeStopped = true; + } + else if (result.key === EscapeSequences_1.C0.DC1) { + this.writeStopped = false; + } + if (result.scrollLines) { + this.scrollLines(result.scrollLines); + return this.cancel(ev, true); + } + if (isThirdLevelShift(this.browser, ev)) { + return true; + } + if (result.cancel) { + this.cancel(ev, true); + } + if (!result.key) { + return true; + } + this.emit('keydown', ev); + this.emit('key', result.key, ev); + this.showCursor(); + this.handler(result.key); + return this.cancel(ev, true); + }; + Terminal.prototype._evaluateKeyEscapeSequence = function (ev) { + var result = { + cancel: false, + key: undefined, + scrollLines: undefined + }; + var modifiers = (ev.shiftKey ? 1 : 0) | (ev.altKey ? 2 : 0) | (ev.ctrlKey ? 4 : 0) | (ev.metaKey ? 8 : 0); + switch (ev.keyCode) { + case 0: + if (ev.key === 'UIKeyInputUpArrow') { + if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OA'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[A'; + } + } + else if (ev.key === 'UIKeyInputLeftArrow') { + if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OD'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[D'; + } + } + else if (ev.key === 'UIKeyInputRightArrow') { + if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OC'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[C'; + } + } + else if (ev.key === 'UIKeyInputDownArrow') { + if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OB'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[B'; + } + } + break; + case 8: + if (ev.shiftKey) { + result.key = EscapeSequences_1.C0.BS; + break; + } + else if (ev.altKey) { + result.key = EscapeSequences_1.C0.ESC + EscapeSequences_1.C0.DEL; + break; + } + result.key = EscapeSequences_1.C0.DEL; + break; + case 9: + if (ev.shiftKey) { + result.key = EscapeSequences_1.C0.ESC + '[Z'; + break; + } + result.key = EscapeSequences_1.C0.HT; + result.cancel = true; + break; + case 13: + result.key = EscapeSequences_1.C0.CR; + result.cancel = true; + break; + case 27: + result.key = EscapeSequences_1.C0.ESC; + result.cancel = true; + break; + case 37: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'D'; + if (result.key === EscapeSequences_1.C0.ESC + '[1;3D') { + result.key = (this.browser.isMac) ? EscapeSequences_1.C0.ESC + 'b' : EscapeSequences_1.C0.ESC + '[1;5D'; + } + } + else if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OD'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[D'; + } + break; + case 39: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'C'; + if (result.key === EscapeSequences_1.C0.ESC + '[1;3C') { + result.key = (this.browser.isMac) ? EscapeSequences_1.C0.ESC + 'f' : EscapeSequences_1.C0.ESC + '[1;5C'; + } + } + else if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OC'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[C'; + } + break; + case 38: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'A'; + if (result.key === EscapeSequences_1.C0.ESC + '[1;3A') { + result.key = EscapeSequences_1.C0.ESC + '[1;5A'; + } + } + else if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OA'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[A'; + } + break; + case 40: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'B'; + if (result.key === EscapeSequences_1.C0.ESC + '[1;3B') { + result.key = EscapeSequences_1.C0.ESC + '[1;5B'; + } + } + else if (this.applicationCursor) { + result.key = EscapeSequences_1.C0.ESC + 'OB'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[B'; + } + break; + case 45: + if (!ev.shiftKey && !ev.ctrlKey) { + result.key = EscapeSequences_1.C0.ESC + '[2~'; + } + break; + case 46: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[3;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[3~'; + } + break; + case 36: + if (modifiers) + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'H'; + else if (this.applicationCursor) + result.key = EscapeSequences_1.C0.ESC + 'OH'; + else + result.key = EscapeSequences_1.C0.ESC + '[H'; + break; + case 35: + if (modifiers) + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'F'; + else if (this.applicationCursor) + result.key = EscapeSequences_1.C0.ESC + 'OF'; + else + result.key = EscapeSequences_1.C0.ESC + '[F'; + break; + case 33: + if (ev.shiftKey) { + result.scrollLines = -(this.rows - 1); + } + else { + result.key = EscapeSequences_1.C0.ESC + '[5~'; + } + break; + case 34: + if (ev.shiftKey) { + result.scrollLines = this.rows - 1; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[6~'; + } + break; + case 112: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'P'; + } + else { + result.key = EscapeSequences_1.C0.ESC + 'OP'; + } + break; + case 113: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'Q'; + } + else { + result.key = EscapeSequences_1.C0.ESC + 'OQ'; + } + break; + case 114: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'R'; + } + else { + result.key = EscapeSequences_1.C0.ESC + 'OR'; + } + break; + case 115: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[1;' + (modifiers + 1) + 'S'; + } + else { + result.key = EscapeSequences_1.C0.ESC + 'OS'; + } + break; + case 116: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[15;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[15~'; + } + break; + case 117: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[17;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[17~'; + } + break; + case 118: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[18;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[18~'; + } + break; + case 119: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[19;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[19~'; + } + break; + case 120: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[20;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[20~'; + } + break; + case 121: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[21;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[21~'; + } + break; + case 122: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[23;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[23~'; + } + break; + case 123: + if (modifiers) { + result.key = EscapeSequences_1.C0.ESC + '[24;' + (modifiers + 1) + '~'; + } + else { + result.key = EscapeSequences_1.C0.ESC + '[24~'; + } + break; + default: + if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { + if (ev.keyCode >= 65 && ev.keyCode <= 90) { + result.key = String.fromCharCode(ev.keyCode - 64); + } + else if (ev.keyCode === 32) { + result.key = String.fromCharCode(0); + } + else if (ev.keyCode >= 51 && ev.keyCode <= 55) { + result.key = String.fromCharCode(ev.keyCode - 51 + 27); + } + else if (ev.keyCode === 56) { + result.key = String.fromCharCode(127); + } + else if (ev.keyCode === 219) { + result.key = String.fromCharCode(27); + } + else if (ev.keyCode === 220) { + result.key = String.fromCharCode(28); + } + else if (ev.keyCode === 221) { + result.key = String.fromCharCode(29); + } + } + else if (!this.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) { + if (ev.keyCode >= 65 && ev.keyCode <= 90) { + result.key = EscapeSequences_1.C0.ESC + String.fromCharCode(ev.keyCode + 32); + } + else if (ev.keyCode === 192) { + result.key = EscapeSequences_1.C0.ESC + '`'; + } + else if (ev.keyCode >= 48 && ev.keyCode <= 57) { + result.key = EscapeSequences_1.C0.ESC + (ev.keyCode - 48); + } + } + else if (this.browser.isMac && !ev.altKey && !ev.ctrlKey && ev.metaKey) { + if (ev.keyCode === 65) { + this.selectAll(); + } + } + break; + } + return result; + }; + Terminal.prototype.setgLevel = function (g) { + this.glevel = g; + this.charset = this.charsets[g]; + }; + Terminal.prototype.setgCharset = function (g, charset) { + this.charsets[g] = charset; + if (this.glevel === g) { + this.charset = charset; + } + }; + Terminal.prototype._keyPress = function (ev) { + var key; + if (this.customKeyEventHandler && this.customKeyEventHandler(ev) === false) { + return false; + } + this.cancel(ev); + if (ev.charCode) { + key = ev.charCode; + } + else if (ev.which == null) { + key = ev.keyCode; + } + else if (ev.which !== 0 && ev.charCode !== 0) { + key = ev.which; + } + else { + return false; + } + if (!key || ((ev.altKey || ev.ctrlKey || ev.metaKey) && !isThirdLevelShift(this.browser, ev))) { + return false; + } + key = String.fromCharCode(key); + this.emit('keypress', key, ev); + this.emit('key', key, ev); + this.showCursor(); + this.handler(key); + return true; + }; + Terminal.prototype.send = function (data) { + var _this = this; + if (!this.sendDataQueue) { + setTimeout(function () { + _this.handler(_this.sendDataQueue); + _this.sendDataQueue = ''; + }, 1); + } + this.sendDataQueue += data; + }; + Terminal.prototype.bell = function () { + var _this = this; + this.emit('bell'); + if (this.soundBell()) + this.bellAudioElement.play(); + if (this.visualBell()) { + this.element.classList.add('visual-bell-active'); + clearTimeout(this.visualBellTimer); + this.visualBellTimer = window.setTimeout(function () { + _this.element.classList.remove('visual-bell-active'); + }, 200); + } + }; + Terminal.prototype.log = function (text, data) { + if (!this.options.debug) + return; + if (!this.context.console || !this.context.console.log) + return; + this.context.console.log(text, data); + }; + Terminal.prototype.error = function (text, data) { + if (!this.options.debug) + return; + if (!this.context.console || !this.context.console.error) + return; + this.context.console.error(text, data); + }; + Terminal.prototype.resize = function (x, y) { + if (isNaN(x) || isNaN(y)) { + return; + } + if (x === this.cols && y === this.rows) { + if (!this.charMeasure.width || !this.charMeasure.height) { + this.charMeasure.measure(this.options); + } + return; + } + if (x < 1) + x = 1; + if (y < 1) + y = 1; + this.buffers.resize(x, y); + this.cols = x; + this.rows = y; + this.buffers.setupTabStops(this.cols); + this.charMeasure.measure(this.options); + this.refresh(0, this.rows - 1); + this.emit('resize', { cols: x, rows: y }); + }; + Terminal.prototype.updateRange = function (y) { + if (y < this.refreshStart) + this.refreshStart = y; + if (y > this.refreshEnd) + this.refreshEnd = y; + }; + Terminal.prototype.maxRange = function () { + this.refreshStart = 0; + this.refreshEnd = this.rows - 1; + }; + Terminal.prototype.eraseRight = function (x, y) { + var line = this.buffer.lines.get(this.buffer.ybase + y); + if (!line) { + return; + } + var ch = [this.eraseAttr(), ' ', 1, 32]; + for (; x < this.cols; x++) { + line[x] = ch; + } + this.updateRange(y); + }; + Terminal.prototype.eraseLeft = function (x, y) { + var line = this.buffer.lines.get(this.buffer.ybase + y); + if (!line) { + return; + } + var ch = [this.eraseAttr(), ' ', 1, 32]; + x++; + while (x--) { + line[x] = ch; + } + this.updateRange(y); + }; + Terminal.prototype.clear = function () { + if (this.buffer.ybase === 0 && this.buffer.y === 0) { + return; + } + this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y)); + this.buffer.lines.length = 1; + this.buffer.ydisp = 0; + this.buffer.ybase = 0; + this.buffer.y = 0; + for (var i = 1; i < this.rows; i++) { + this.buffer.lines.push(this.blankLine()); + } + this.refresh(0, this.rows - 1); + this.emit('scroll', this.buffer.ydisp); + }; + Terminal.prototype.eraseLine = function (y) { + this.eraseRight(0, y); + }; + Terminal.prototype.blankLine = function (cur, isWrapped, cols) { + var attr = cur ? this.eraseAttr() : this.defAttr; + var ch = [attr, ' ', 1, 32]; + var line = []; + if (isWrapped) { + line.isWrapped = isWrapped; + } + cols = cols || this.cols; + for (var i = 0; i < cols; i++) { + line[i] = ch; + } + return line; + }; + Terminal.prototype.ch = function (cur) { + if (cur) { + return [this.eraseAttr(), ' ', 1, 32]; + } + return [this.defAttr, ' ', 1, 32]; + }; + Terminal.prototype.is = function (term) { + return (this.options.termName + '').indexOf(term) === 0; + }; + Terminal.prototype.handler = function (data) { + if (this.options.disableStdin) { + return; + } + if (this.selectionManager && this.selectionManager.hasSelection) { + this.selectionManager.clearSelection(); + } + if (this.buffer.ybase !== this.buffer.ydisp) { + this.scrollToBottom(); + } + this.emit('data', data); + }; + Terminal.prototype.handleTitle = function (title) { + this.emit('title', title); + }; + Terminal.prototype.index = function () { + this.buffer.y++; + if (this.buffer.y > this.buffer.scrollBottom) { + this.buffer.y--; + this.scroll(); + } + if (this.buffer.x >= this.cols) { + this.buffer.x--; + } + }; + Terminal.prototype.reverseIndex = function () { + if (this.buffer.y === this.buffer.scrollTop) { + var scrollRegionHeight = this.buffer.scrollBottom - this.buffer.scrollTop; + this.buffer.lines.shiftElements(this.buffer.y + this.buffer.ybase, scrollRegionHeight, 1); + this.buffer.lines.set(this.buffer.y + this.buffer.ybase, this.blankLine(true)); + this.updateRange(this.buffer.scrollTop); + this.updateRange(this.buffer.scrollBottom); + } + else { + this.buffer.y--; + } + }; + Terminal.prototype.reset = function () { + this.options.rows = this.rows; + this.options.cols = this.cols; + var customKeyEventHandler = this.customKeyEventHandler; + var inputHandler = this.inputHandler; + var buffers = this.buffers; + this.setup(); + this.customKeyEventHandler = customKeyEventHandler; + this.inputHandler = inputHandler; + this.buffers = buffers; + this.refresh(0, this.rows - 1); + this.viewport.syncScrollArea(); + }; + Terminal.prototype.tabSet = function () { + this.buffer.tabs[this.buffer.x] = true; + }; + Terminal.prototype.cancel = function (ev, force) { + if (!this.options.cancelEvents && !force) { + return; + } + ev.preventDefault(); + ev.stopPropagation(); + return false; + }; + Terminal.prototype.matchColor = function (r1, g1, b1) { + return matchColor_(r1, g1, b1); + }; + Terminal.prototype.visualBell = function () { + return this.options.bellStyle === 'visual' || + this.options.bellStyle === 'both'; + }; + Terminal.prototype.soundBell = function () { + return this.options.bellStyle === 'sound' || + this.options.bellStyle === 'both'; + }; + Terminal.prototype.syncBellSound = function () { + if (!this.element) { + return; + } + if (this.soundBell() && this.bellAudioElement) { + this.bellAudioElement.setAttribute('src', this.options.bellSound); + } + else if (this.soundBell()) { + this.bellAudioElement = document.createElement('audio'); + this.bellAudioElement.setAttribute('preload', 'auto'); + this.bellAudioElement.setAttribute('src', this.options.bellSound); + this.helperContainer.appendChild(this.bellAudioElement); + } + else if (this.bellAudioElement) { + this.helperContainer.removeChild(this.bellAudioElement); + } + }; + return Terminal; +}(EventEmitter_1.EventEmitter)); +exports.Terminal = Terminal; +function globalOn(el, type, handler, capture) { + if (!Array.isArray(el)) { + el = [el]; + } + el.forEach(function (element) { + element.addEventListener(type, handler, capture || false); + }); +} +var on = globalOn; +function off(el, type, handler, capture) { + if (capture === void 0) { capture = false; } + el.removeEventListener(type, handler, capture); +} +function isThirdLevelShift(browser, ev) { + var thirdLevelKey = (browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) || + (browser.isMSWindows && ev.altKey && ev.ctrlKey && !ev.metaKey); + if (ev.type === 'keypress') { + return thirdLevelKey; + } + return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47); +} +function wasMondifierKeyOnlyEvent(ev) { + return ev.keyCode === 16 || + ev.keyCode === 17 || + ev.keyCode === 18; +} +var vcolors = (function () { + var result = ColorManager_1.DEFAULT_ANSI_COLORS.map(function (c) { + c = c.substring(1); + return [ + parseInt(c.substring(0, 2), 16), + parseInt(c.substring(2, 4), 16), + parseInt(c.substring(4, 6), 16) + ]; + }); + var r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]; + for (var i = 0; i < 216; i++) { + result.push([ + r[(i / 36) % 6 | 0], + r[(i / 6) % 6 | 0], + r[i % 6] + ]); + } + var c; + for (var i = 0; i < 24; i++) { + c = 8 + i * 10; + result.push([c, c, c]); + } + return result; +})(); +var matchColorCache = {}; +function matchColorDistance(r1, g1, b1, r2, g2, b2) { + return Math.pow(30 * (r1 - r2), 2) + + Math.pow(59 * (g1 - g2), 2) + + Math.pow(11 * (b1 - b2), 2); +} +; +function matchColor_(r1, g1, b1) { + var hash = (r1 << 16) | (g1 << 8) | b1; + if (matchColorCache[hash] != null) { + return matchColorCache[hash]; + } + var ldiff = Infinity; + var li = -1; + var i = 0; + var c; + var r2; + var g2; + var b2; + var diff; + for (; i < vcolors.length; i++) { + c = vcolors[i]; + r2 = c[0]; + g2 = c[1]; + b2 = c[2]; + diff = matchColorDistance(r1, g1, b1, r2, g2, b2); + if (diff === 0) { + li = i; + break; + } + if (diff < ldiff) { + ldiff = diff; + li = i; + } + } + return matchColorCache[hash] = li; +} + + + +},{"./Buffer":1,"./BufferSet":2,"./CompositionHelper":5,"./EscapeSequences":6,"./EventEmitter":7,"./InputHandler":8,"./Linkifier":9,"./Parser":10,"./SelectionManager":11,"./Viewport":15,"./handlers/Clipboard":16,"./input/MouseZoneManager":17,"./renderer/CharAtlas":19,"./renderer/ColorManager":20,"./renderer/Renderer":24,"./utils/Browser":28,"./utils/CharMeasure":29,"./utils/MouseHelper":32,"./utils/Sounds":34}],14:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var LinkHoverEventTypes; +(function (LinkHoverEventTypes) { + LinkHoverEventTypes["HOVER"] = "linkhover"; + LinkHoverEventTypes["TOOLTIP"] = "linktooltip"; + LinkHoverEventTypes["LEAVE"] = "linkleave"; +})(LinkHoverEventTypes = exports.LinkHoverEventTypes || (exports.LinkHoverEventTypes = {})); +; + + + +},{}],15:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Viewport = (function () { + function Viewport(terminal, viewportElement, scrollArea, charMeasure) { + var _this = this; + this.terminal = terminal; + this.viewportElement = viewportElement; + this.scrollArea = scrollArea; + this.charMeasure = charMeasure; + this.currentRowHeight = 0; + this.lastRecordedBufferLength = 0; + this.lastRecordedViewportHeight = 0; + this.lastRecordedBufferHeight = 0; + this.viewportElement.addEventListener('scroll', this.onScroll.bind(this)); + setTimeout(function () { return _this.syncScrollArea(); }, 0); + } + Viewport.prototype.onThemeChanged = function (colors) { + this.viewportElement.style.backgroundColor = colors.background; + }; + Viewport.prototype.refresh = function () { + if (this.charMeasure.height > 0) { + this.currentRowHeight = this.terminal.renderer.dimensions.scaledCellHeight / window.devicePixelRatio; + if (this.lastRecordedViewportHeight !== this.terminal.renderer.dimensions.canvasHeight) { + this.lastRecordedViewportHeight = this.terminal.renderer.dimensions.canvasHeight; + this.viewportElement.style.height = this.lastRecordedViewportHeight + 'px'; + } + var newBufferHeight = Math.round(this.currentRowHeight * this.lastRecordedBufferLength); + if (this.lastRecordedBufferHeight !== newBufferHeight) { + this.lastRecordedBufferHeight = newBufferHeight; + this.scrollArea.style.height = this.lastRecordedBufferHeight + 'px'; + } + } + }; + Viewport.prototype.syncScrollArea = function () { + if (this.lastRecordedBufferLength !== this.terminal.buffer.lines.length) { + this.lastRecordedBufferLength = this.terminal.buffer.lines.length; + this.refresh(); + } + else if (this.lastRecordedViewportHeight !== this.terminal.renderer.dimensions.canvasHeight) { + this.refresh(); + } + else { + if (this.terminal.renderer.dimensions.scaledCellHeight / window.devicePixelRatio !== this.currentRowHeight) { + this.refresh(); + } + } + var scrollTop = this.terminal.buffer.ydisp * this.currentRowHeight; + if (this.viewportElement.scrollTop !== scrollTop) { + this.viewportElement.scrollTop = scrollTop; + } + }; + Viewport.prototype.onScroll = function (ev) { + var newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight); + var diff = newRow - this.terminal.buffer.ydisp; + this.terminal.scrollLines(diff, true); + }; + Viewport.prototype.onWheel = function (ev) { + if (ev.deltaY === 0) { + return; + } + var multiplier = 1; + if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) { + multiplier = this.currentRowHeight; + } + else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) { + multiplier = this.currentRowHeight * this.terminal.rows; + } + this.viewportElement.scrollTop += ev.deltaY * multiplier; + ev.preventDefault(); + }; + ; + Viewport.prototype.onTouchStart = function (ev) { + this.lastTouchY = ev.touches[0].pageY; + }; + ; + Viewport.prototype.onTouchMove = function (ev) { + var deltaY = this.lastTouchY - ev.touches[0].pageY; + this.lastTouchY = ev.touches[0].pageY; + if (deltaY === 0) { + return; + } + this.viewportElement.scrollTop += deltaY; + ev.preventDefault(); + }; + ; + return Viewport; +}()); +exports.Viewport = Viewport; + + + +},{}],16:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function prepareTextForTerminal(text, isMSWindows) { + if (isMSWindows) { + return text.replace(/\r?\n/g, '\r'); + } + return text; +} +exports.prepareTextForTerminal = prepareTextForTerminal; +function bracketTextForPaste(text, bracketedPasteMode) { + if (bracketedPasteMode) { + return '\x1b[200~' + text + '\x1b[201~'; + } + return text; +} +exports.bracketTextForPaste = bracketTextForPaste; +function copyHandler(ev, term, selectionManager) { + if (term.browser.isMSIE) { + window.clipboardData.setData('Text', selectionManager.selectionText); + } + else { + ev.clipboardData.setData('text/plain', selectionManager.selectionText); + } + ev.preventDefault(); +} +exports.copyHandler = copyHandler; +function pasteHandler(ev, term) { + ev.stopPropagation(); + var text; + var dispatchPaste = function (text) { + text = prepareTextForTerminal(text, term.browser.isMSWindows); + text = bracketTextForPaste(text, term.bracketedPasteMode); + term.handler(text); + term.textarea.value = ''; + term.emit('paste', text); + term.cancel(ev); + }; + if (term.browser.isMSIE) { + if (window.clipboardData) { + text = window.clipboardData.getData('Text'); + dispatchPaste(text); + } + } + else { + if (ev.clipboardData) { + text = ev.clipboardData.getData('text/plain'); + dispatchPaste(text); + } + } +} +exports.pasteHandler = pasteHandler; +function moveTextAreaUnderMouseCursor(ev, textarea) { + textarea.style.position = 'fixed'; + textarea.style.width = '20px'; + textarea.style.height = '20px'; + textarea.style.left = (ev.clientX - 10) + 'px'; + textarea.style.top = (ev.clientY - 10) + 'px'; + textarea.style.zIndex = '1000'; + textarea.focus(); + setTimeout(function () { + textarea.style.position = null; + textarea.style.width = null; + textarea.style.height = null; + textarea.style.left = null; + textarea.style.top = null; + textarea.style.zIndex = null; + }, 4); +} +exports.moveTextAreaUnderMouseCursor = moveTextAreaUnderMouseCursor; +function rightClickHandler(ev, textarea, selectionManager) { + moveTextAreaUnderMouseCursor(ev, textarea); + textarea.value = selectionManager.selectionText; + textarea.select(); +} +exports.rightClickHandler = rightClickHandler; + + + +},{}],17:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var HOVER_DURATION = 500; +var MouseZoneManager = (function () { + function MouseZoneManager(_terminal) { + var _this = this; + this._terminal = _terminal; + this._zones = []; + this._areZonesActive = false; + this._tooltipTimeout = null; + this._currentZone = null; + this._lastHoverCoords = [null, null]; + this._terminal.element.addEventListener('mousedown', function (e) { return _this._onMouseDown(e); }); + this._mouseMoveListener = function (e) { return _this._onMouseMove(e); }; + this._clickListener = function (e) { return _this._onClick(e); }; + } + MouseZoneManager.prototype.add = function (zone) { + this._zones.push(zone); + if (this._zones.length === 1) { + this._activate(); + } + }; + MouseZoneManager.prototype.clearAll = function (start, end) { + if (this._zones.length === 0) { + return; + } + if (!end) { + start = 0; + end = this._terminal.rows - 1; + } + for (var i = 0; i < this._zones.length; i++) { + var zone = this._zones[i]; + if (zone.y > start && zone.y <= end + 1) { + if (this._currentZone && this._currentZone === zone) { + this._currentZone.leaveCallback(); + this._currentZone = null; + } + this._zones.splice(i--, 1); + } + } + if (this._zones.length === 0) { + this._deactivate(); + } + }; + MouseZoneManager.prototype._activate = function () { + if (!this._areZonesActive) { + this._areZonesActive = true; + this._terminal.element.addEventListener('mousemove', this._mouseMoveListener); + this._terminal.element.addEventListener('click', this._clickListener); + } + }; + MouseZoneManager.prototype._deactivate = function () { + if (this._areZonesActive) { + this._areZonesActive = false; + this._terminal.element.removeEventListener('mousemove', this._mouseMoveListener); + this._terminal.element.removeEventListener('click', this._clickListener); + } + }; + MouseZoneManager.prototype._onMouseMove = function (e) { + if (this._lastHoverCoords[0] !== e.pageX || this._lastHoverCoords[1] !== e.pageY) { + this._onHover(e); + this._lastHoverCoords = [e.pageX, e.pageY]; + } + }; + MouseZoneManager.prototype._onHover = function (e) { + var _this = this; + var zone = this._findZoneEventAt(e); + if (zone === this._currentZone) { + return; + } + if (this._currentZone) { + this._currentZone.leaveCallback(); + this._currentZone = null; + if (this._tooltipTimeout) { + clearTimeout(this._tooltipTimeout); + } + } + if (!zone) { + return; + } + this._currentZone = zone; + if (zone.hoverCallback) { + zone.hoverCallback(e); + } + this._tooltipTimeout = setTimeout(function () { return _this._onTooltip(e); }, HOVER_DURATION); + }; + MouseZoneManager.prototype._onTooltip = function (e) { + this._tooltipTimeout = null; + var zone = this._findZoneEventAt(e); + if (zone && zone.tooltipCallback) { + zone.tooltipCallback(e); + } + }; + MouseZoneManager.prototype._onMouseDown = function (e) { + if (!this._areZonesActive) { + return; + } + var zone = this._findZoneEventAt(e); + if (zone) { + e.preventDefault(); + e.stopImmediatePropagation(); + } + }; + MouseZoneManager.prototype._onClick = function (e) { + var zone = this._findZoneEventAt(e); + if (zone) { + zone.clickCallback(e); + e.preventDefault(); + e.stopImmediatePropagation(); + } + }; + MouseZoneManager.prototype._findZoneEventAt = function (e) { + var coords = this._terminal.mouseHelper.getCoords(e, this._terminal.element, this._terminal.charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows); + if (!coords) { + return null; + } + for (var i = 0; i < this._zones.length; i++) { + var zone = this._zones[i]; + if (zone.y === coords[1] && zone.x1 <= coords[0] && zone.x2 > coords[0]) { + return zone; + } + } + ; + return null; + }; + return MouseZoneManager; +}()); +exports.MouseZoneManager = MouseZoneManager; +var MouseZone = (function () { + function MouseZone(x1, x2, y, clickCallback, hoverCallback, tooltipCallback, leaveCallback) { + this.x1 = x1; + this.x2 = x2; + this.y = y; + this.clickCallback = clickCallback; + this.hoverCallback = hoverCallback; + this.tooltipCallback = tooltipCallback; + this.leaveCallback = leaveCallback; + } + return MouseZone; +}()); +exports.MouseZone = MouseZone; + + + +},{}],18:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var CharAtlas_1 = require("./CharAtlas"); +var Buffer_1 = require("../Buffer"); +exports.INVERTED_DEFAULT_COLOR = -1; +var DIM_OPACITY = 0.5; +var BaseRenderLayer = (function () { + function BaseRenderLayer(container, id, zIndex, _alpha, _colors) { + this._alpha = _alpha; + this._colors = _colors; + this._scaledCharWidth = 0; + this._scaledCharHeight = 0; + this._scaledCellWidth = 0; + this._scaledCellHeight = 0; + this._scaledCharLeft = 0; + this._scaledCharTop = 0; + this._canvas = document.createElement('canvas'); + this._canvas.id = "xterm-" + id + "-layer"; + this._canvas.style.zIndex = zIndex.toString(); + this._ctx = this._canvas.getContext('2d', { alpha: _alpha }); + this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); + if (!_alpha) { + this.clearAll(); + } + container.appendChild(this._canvas); + } + BaseRenderLayer.prototype.onOptionsChanged = function (terminal) { }; + BaseRenderLayer.prototype.onBlur = function (terminal) { }; + BaseRenderLayer.prototype.onFocus = function (terminal) { }; + BaseRenderLayer.prototype.onCursorMove = function (terminal) { }; + BaseRenderLayer.prototype.onGridChanged = function (terminal, startRow, endRow) { }; + BaseRenderLayer.prototype.onSelectionChanged = function (terminal, start, end) { }; + BaseRenderLayer.prototype.onThemeChanged = function (terminal, colorSet) { + this._refreshCharAtlas(terminal, colorSet); + }; + BaseRenderLayer.prototype._refreshCharAtlas = function (terminal, colorSet) { + var _this = this; + if (this._scaledCharWidth <= 0 && this._scaledCharHeight <= 0) { + return; + } + this._charAtlas = null; + var result = CharAtlas_1.acquireCharAtlas(terminal, this._colors, this._scaledCharWidth, this._scaledCharHeight); + if (result instanceof HTMLCanvasElement) { + this._charAtlas = result; + } + else { + result.then(function (bitmap) { return _this._charAtlas = bitmap; }); + } + }; + BaseRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) { + this._scaledCellWidth = dim.scaledCellWidth; + this._scaledCellHeight = dim.scaledCellHeight; + this._scaledCharWidth = dim.scaledCharWidth; + this._scaledCharHeight = dim.scaledCharHeight; + this._scaledCharLeft = dim.scaledCharLeft; + this._scaledCharTop = dim.scaledCharTop; + this._canvas.width = dim.scaledCanvasWidth; + this._canvas.height = dim.scaledCanvasHeight; + this._canvas.style.width = dim.canvasWidth + "px"; + this._canvas.style.height = dim.canvasHeight + "px"; + if (!this._alpha) { + this.clearAll(); + } + if (charSizeChanged) { + this._refreshCharAtlas(terminal, this._colors); + } + }; + BaseRenderLayer.prototype.fillCells = function (x, y, width, height) { + this._ctx.fillRect(x * this._scaledCellWidth, y * this._scaledCellHeight, width * this._scaledCellWidth, height * this._scaledCellHeight); + }; + BaseRenderLayer.prototype.fillBottomLineAtCells = function (x, y, width) { + if (width === void 0) { width = 1; } + this._ctx.fillRect(x * this._scaledCellWidth, (y + 1) * this._scaledCellHeight - window.devicePixelRatio - 1, width * this._scaledCellWidth, window.devicePixelRatio); + }; + BaseRenderLayer.prototype.fillLeftLineAtCell = function (x, y) { + this._ctx.fillRect(x * this._scaledCellWidth, y * this._scaledCellHeight, window.devicePixelRatio, this._scaledCellHeight); + }; + BaseRenderLayer.prototype.strokeRectAtCell = function (x, y, width, height) { + this._ctx.lineWidth = window.devicePixelRatio; + this._ctx.strokeRect(x * this._scaledCellWidth + window.devicePixelRatio / 2, y * this._scaledCellHeight + (window.devicePixelRatio / 2), width * this._scaledCellWidth - window.devicePixelRatio, (height * this._scaledCellHeight) - window.devicePixelRatio); + }; + BaseRenderLayer.prototype.clearAll = function () { + if (this._alpha) { + this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); + } + else { + this._ctx.fillStyle = this._colors.background; + this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height); + } + }; + BaseRenderLayer.prototype.clearCells = function (x, y, width, height) { + if (this._alpha) { + this._ctx.clearRect(x * this._scaledCellWidth, y * this._scaledCellHeight, width * this._scaledCellWidth, height * this._scaledCellHeight); + } + else { + this._ctx.fillStyle = this._colors.background; + this._ctx.fillRect(x * this._scaledCellWidth, y * this._scaledCellHeight, width * this._scaledCellWidth, height * this._scaledCellHeight); + } + }; + BaseRenderLayer.prototype.fillCharTrueColor = function (terminal, charData, x, y) { + this._ctx.font = terminal.options.fontSize * window.devicePixelRatio + "px " + terminal.options.fontFamily; + this._ctx.textBaseline = 'top'; + this._clipRow(terminal, y); + this._ctx.fillText(charData[Buffer_1.CHAR_DATA_CHAR_INDEX], x * this._scaledCellWidth + this._scaledCharLeft, y * this._scaledCellHeight + this._scaledCharTop); + }; + BaseRenderLayer.prototype.drawChar = function (terminal, char, code, width, x, y, fg, bg, bold, dim) { + var colorIndex = 0; + if (fg < 256) { + colorIndex = fg + 2; + } + else { + if (bold && terminal.options.enableBold) { + colorIndex = 1; + } + } + var isAscii = code < 256; + var isBasicColor = (colorIndex > 1 && fg < 16) && (fg < 8 || bold); + var isDefaultColor = fg >= 256; + var isDefaultBackground = bg >= 256; + if (this._charAtlas && isAscii && (isBasicColor || isDefaultColor) && isDefaultBackground) { + var charAtlasCellWidth = this._scaledCharWidth + CharAtlas_1.CHAR_ATLAS_CELL_SPACING; + var charAtlasCellHeight = this._scaledCharHeight + CharAtlas_1.CHAR_ATLAS_CELL_SPACING; + if (dim) { + this._ctx.globalAlpha = DIM_OPACITY; + } + if (bold && !terminal.options.enableBold) { + if (colorIndex > 1) { + colorIndex -= 8; + } + } + this._ctx.drawImage(this._charAtlas, code * charAtlasCellWidth, colorIndex * charAtlasCellHeight, charAtlasCellWidth, this._scaledCharHeight, x * this._scaledCellWidth + this._scaledCharLeft, y * this._scaledCellHeight + this._scaledCharTop, charAtlasCellWidth, this._scaledCharHeight); + } + else { + this._drawUncachedChar(terminal, char, width, fg, x, y, bold, dim); + } + }; + BaseRenderLayer.prototype._drawUncachedChar = function (terminal, char, width, fg, x, y, bold, dim) { + this._ctx.save(); + this._ctx.font = terminal.options.fontSize * window.devicePixelRatio + "px " + terminal.options.fontFamily; + if (bold && terminal.options.enableBold) { + this._ctx.font = "bold " + this._ctx.font; + } + this._ctx.textBaseline = 'top'; + if (fg === exports.INVERTED_DEFAULT_COLOR) { + this._ctx.fillStyle = this._colors.background; + } + else if (fg < 256) { + this._ctx.fillStyle = this._colors.ansi[fg]; + } + else { + this._ctx.fillStyle = this._colors.foreground; + } + this._clipRow(terminal, y); + if (dim) { + this._ctx.globalAlpha = DIM_OPACITY; + } + this._ctx.fillText(char, x * this._scaledCellWidth + this._scaledCharLeft, y * this._scaledCellHeight + this._scaledCharTop); + this._ctx.restore(); + }; + BaseRenderLayer.prototype._clipRow = function (terminal, y) { + this._ctx.beginPath(); + this._ctx.rect(0, y * this._scaledCellHeight, terminal.cols * this._scaledCellWidth, this._scaledCellHeight); + this._ctx.clip(); + }; + return BaseRenderLayer; +}()); +exports.BaseRenderLayer = BaseRenderLayer; + + + +},{"../Buffer":1,"./CharAtlas":19}],19:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Browser_1 = require("../utils/Browser"); +exports.CHAR_ATLAS_CELL_SPACING = 1; +var charAtlasCache = []; +function acquireCharAtlas(terminal, colors, scaledCharWidth, scaledCharHeight) { + var newConfig = generateConfig(scaledCharWidth, scaledCharHeight, terminal, colors); + for (var i = 0; i < charAtlasCache.length; i++) { + var entry = charAtlasCache[i]; + var ownedByIndex = entry.ownedBy.indexOf(terminal); + if (ownedByIndex >= 0) { + if (configEquals(entry.config, newConfig)) { + return entry.bitmap; + } + else { + if (entry.ownedBy.length === 1) { + charAtlasCache.splice(i, 1); + } + else { + entry.ownedBy.splice(ownedByIndex, 1); + } + break; + } + } + } + for (var i = 0; i < charAtlasCache.length; i++) { + var entry = charAtlasCache[i]; + if (configEquals(entry.config, newConfig)) { + entry.ownedBy.push(terminal); + return entry.bitmap; + } + } + var newEntry = { + bitmap: generator.generate(scaledCharWidth, scaledCharHeight, terminal.options.fontSize, terminal.options.fontFamily, colors.background, colors.foreground, colors.ansi), + config: newConfig, + ownedBy: [terminal] + }; + charAtlasCache.push(newEntry); + return newEntry.bitmap; +} +exports.acquireCharAtlas = acquireCharAtlas; +function generateConfig(scaledCharWidth, scaledCharHeight, terminal, colors) { + var clonedColors = { + foreground: colors.foreground, + background: colors.background, + cursor: null, + cursorAccent: null, + selection: null, + ansi: colors.ansi.slice(0, 16) + }; + return { + scaledCharWidth: scaledCharWidth, + scaledCharHeight: scaledCharHeight, + fontFamily: terminal.options.fontFamily, + fontSize: terminal.options.fontSize, + colors: clonedColors + }; +} +function configEquals(a, b) { + for (var i = 0; i < a.colors.ansi.length; i++) { + if (a.colors.ansi[i] !== b.colors.ansi[i]) { + return false; + } + } + return a.fontFamily === b.fontFamily && + a.fontSize === b.fontSize && + a.scaledCharWidth === b.scaledCharWidth && + a.scaledCharHeight === b.scaledCharHeight && + a.colors.foreground === b.colors.foreground && + a.colors.background === b.colors.background; +} +var generator; +function initialize(document, alpha) { + if (!generator) { + generator = new CharAtlasGenerator(document, alpha); + } +} +exports.initialize = initialize; +var CharAtlasGenerator = (function () { + function CharAtlasGenerator(_document, alpha) { + this._document = _document; + this._canvas = this._document.createElement('canvas'); + this._ctx = this._canvas.getContext('2d', { alpha: alpha }); + this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); + } + CharAtlasGenerator.prototype.generate = function (scaledCharWidth, scaledCharHeight, fontSize, fontFamily, background, foreground, ansiColors) { + var cellWidth = scaledCharWidth + exports.CHAR_ATLAS_CELL_SPACING; + var cellHeight = scaledCharHeight + exports.CHAR_ATLAS_CELL_SPACING; + this._canvas.width = 255 * cellWidth; + this._canvas.height = (2 + 16) * cellHeight; + this._ctx.fillStyle = background; + this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height); + this._ctx.save(); + this._ctx.fillStyle = foreground; + this._ctx.font = fontSize * window.devicePixelRatio + "px " + fontFamily; + this._ctx.textBaseline = 'top'; + for (var i = 0; i < 256; i++) { + this._ctx.save(); + this._ctx.beginPath(); + this._ctx.rect(i * cellWidth, 0, cellWidth, cellHeight); + this._ctx.clip(); + this._ctx.fillText(String.fromCharCode(i), i * cellWidth, 0); + this._ctx.restore(); + } + this._ctx.save(); + this._ctx.font = "bold " + this._ctx.font; + for (var i = 0; i < 256; i++) { + this._ctx.save(); + this._ctx.beginPath(); + this._ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight); + this._ctx.clip(); + this._ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight); + this._ctx.restore(); + } + this._ctx.restore(); + this._ctx.font = fontSize * window.devicePixelRatio + "px " + fontFamily; + for (var colorIndex = 0; colorIndex < 16; colorIndex++) { + if (colorIndex === 8) { + this._ctx.font = "bold " + this._ctx.font; + } + var y = (colorIndex + 2) * cellHeight; + for (var i = 0; i < 256; i++) { + this._ctx.save(); + this._ctx.beginPath(); + this._ctx.rect(i * cellWidth, y, cellWidth, cellHeight); + this._ctx.clip(); + this._ctx.fillStyle = ansiColors[colorIndex]; + this._ctx.fillText(String.fromCharCode(i), i * cellWidth, y); + this._ctx.restore(); + } + } + this._ctx.restore(); + if (!('createImageBitmap' in window) || Browser_1.isFirefox) { + var result = this._canvas; + this._canvas = this._document.createElement('canvas'); + this._ctx = this._canvas.getContext('2d'); + this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); + return result; + } + var charAtlasImageData = this._ctx.getImageData(0, 0, this._canvas.width, this._canvas.height); + var r = parseInt(background.substr(1, 2), 16); + var g = parseInt(background.substr(3, 2), 16); + var b = parseInt(background.substr(5, 2), 16); + this._clearColor(charAtlasImageData, r, g, b); + var promise = window.createImageBitmap(charAtlasImageData); + this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); + return promise; + }; + CharAtlasGenerator.prototype._clearColor = function (imageData, r, g, b) { + for (var offset = 0; offset < imageData.data.length; offset += 4) { + if (imageData.data[offset] === r && + imageData.data[offset + 1] === g && + imageData.data[offset + 2] === b) { + imageData.data[offset + 3] = 0; + } + } + }; + return CharAtlasGenerator; +}()); + + + +},{"../utils/Browser":28}],20:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var DEFAULT_FOREGROUND = '#ffffff'; +var DEFAULT_BACKGROUND = '#000000'; +var DEFAULT_CURSOR = '#ffffff'; +var DEFAULT_CURSOR_ACCENT = '#000000'; +var DEFAULT_SELECTION = 'rgba(255, 255, 255, 0.3)'; +exports.DEFAULT_ANSI_COLORS = [ + '#2e3436', + '#cc0000', + '#4e9a06', + '#c4a000', + '#3465a4', + '#75507b', + '#06989a', + '#d3d7cf', + '#555753', + '#ef2929', + '#8ae234', + '#fce94f', + '#729fcf', + '#ad7fa8', + '#34e2e2', + '#eeeeec' +]; +function generate256Colors(first16Colors) { + var colors = first16Colors.slice(); + var v = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]; + for (var i = 0; i < 216; i++) { + var r = toPaddedHex(v[(i / 36) % 6 | 0]); + var g = toPaddedHex(v[(i / 6) % 6 | 0]); + var b = toPaddedHex(v[i % 6]); + colors.push("#" + r + g + b); + } + for (var i = 0; i < 24; i++) { + var c = toPaddedHex(8 + i * 10); + colors.push("#" + c + c + c); + } + return colors; +} +function toPaddedHex(c) { + var s = c.toString(16); + return s.length < 2 ? '0' + s : s; +} +var ColorManager = (function () { + function ColorManager() { + this.colors = { + foreground: DEFAULT_FOREGROUND, + background: DEFAULT_BACKGROUND, + cursor: DEFAULT_CURSOR, + cursorAccent: DEFAULT_CURSOR_ACCENT, + selection: DEFAULT_SELECTION, + ansi: generate256Colors(exports.DEFAULT_ANSI_COLORS) + }; + } + ColorManager.prototype.setTheme = function (theme) { + this.colors.foreground = theme.foreground || DEFAULT_FOREGROUND; + this.colors.background = theme.background || DEFAULT_BACKGROUND; + this.colors.cursor = theme.cursor || DEFAULT_CURSOR; + this.colors.cursorAccent = theme.cursorAccent || DEFAULT_CURSOR_ACCENT; + this.colors.selection = theme.selection || DEFAULT_SELECTION; + this.colors.ansi[0] = theme.black || exports.DEFAULT_ANSI_COLORS[0]; + this.colors.ansi[1] = theme.red || exports.DEFAULT_ANSI_COLORS[1]; + this.colors.ansi[2] = theme.green || exports.DEFAULT_ANSI_COLORS[2]; + this.colors.ansi[3] = theme.yellow || exports.DEFAULT_ANSI_COLORS[3]; + this.colors.ansi[4] = theme.blue || exports.DEFAULT_ANSI_COLORS[4]; + this.colors.ansi[5] = theme.magenta || exports.DEFAULT_ANSI_COLORS[5]; + this.colors.ansi[6] = theme.cyan || exports.DEFAULT_ANSI_COLORS[6]; + this.colors.ansi[7] = theme.white || exports.DEFAULT_ANSI_COLORS[7]; + this.colors.ansi[8] = theme.brightBlack || exports.DEFAULT_ANSI_COLORS[8]; + this.colors.ansi[9] = theme.brightRed || exports.DEFAULT_ANSI_COLORS[9]; + this.colors.ansi[10] = theme.brightGreen || exports.DEFAULT_ANSI_COLORS[10]; + this.colors.ansi[11] = theme.brightYellow || exports.DEFAULT_ANSI_COLORS[11]; + this.colors.ansi[12] = theme.brightBlue || exports.DEFAULT_ANSI_COLORS[12]; + this.colors.ansi[13] = theme.brightMagenta || exports.DEFAULT_ANSI_COLORS[13]; + this.colors.ansi[14] = theme.brightCyan || exports.DEFAULT_ANSI_COLORS[14]; + this.colors.ansi[15] = theme.brightWhite || exports.DEFAULT_ANSI_COLORS[15]; + }; + return ColorManager; +}()); +exports.ColorManager = ColorManager; + + + +},{}],21:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Buffer_1 = require("../Buffer"); +var BaseRenderLayer_1 = require("./BaseRenderLayer"); +var BLINK_INTERVAL = 600; +var CursorRenderLayer = (function (_super) { + __extends(CursorRenderLayer, _super); + function CursorRenderLayer(container, zIndex, colors) { + var _this = _super.call(this, container, 'cursor', zIndex, true, colors) || this; + _this._state = { + x: null, + y: null, + isFocused: null, + style: null, + width: null, + }; + _this._cursorRenderers = { + 'bar': _this._renderBarCursor.bind(_this), + 'block': _this._renderBlockCursor.bind(_this), + 'underline': _this._renderUnderlineCursor.bind(_this) + }; + return _this; + } + CursorRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) { + _super.prototype.resize.call(this, terminal, dim, charSizeChanged); + this._state = { + x: null, + y: null, + isFocused: null, + style: null, + width: null, + }; + }; + CursorRenderLayer.prototype.reset = function (terminal) { + this._clearCursor(); + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.dispose(); + this._cursorBlinkStateManager = null; + this.onOptionsChanged(terminal); + } + }; + CursorRenderLayer.prototype.onBlur = function (terminal) { + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.pause(); + } + terminal.refresh(terminal.buffer.y, terminal.buffer.y); + }; + CursorRenderLayer.prototype.onFocus = function (terminal) { + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.resume(terminal); + } + else { + terminal.refresh(terminal.buffer.y, terminal.buffer.y); + } + }; + CursorRenderLayer.prototype.onOptionsChanged = function (terminal) { + var _this = this; + if (terminal.options.cursorBlink) { + if (!this._cursorBlinkStateManager) { + this._cursorBlinkStateManager = new CursorBlinkStateManager(terminal, function () { + _this._render(terminal, true); + }); + } + } + else { + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.dispose(); + this._cursorBlinkStateManager = null; + } + terminal.refresh(terminal.buffer.y, terminal.buffer.y); + } + }; + CursorRenderLayer.prototype.onCursorMove = function (terminal) { + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.restartBlinkAnimation(terminal); + } + }; + CursorRenderLayer.prototype.onGridChanged = function (terminal, startRow, endRow) { + if (!this._cursorBlinkStateManager || this._cursorBlinkStateManager.isPaused) { + this._render(terminal, false); + } + }; + CursorRenderLayer.prototype._render = function (terminal, triggeredByAnimationFrame) { + if (!terminal.cursorState || terminal.cursorHidden) { + this._clearCursor(); + return; + } + var cursorY = terminal.buffer.ybase + terminal.buffer.y; + var viewportRelativeCursorY = cursorY - terminal.buffer.ydisp; + if (viewportRelativeCursorY < 0 || viewportRelativeCursorY >= terminal.rows) { + this._clearCursor(); + return; + } + var charData = terminal.buffer.lines.get(cursorY)[terminal.buffer.x]; + if (!charData) { + return; + } + if (!terminal.isFocused) { + this._clearCursor(); + this._ctx.save(); + this._ctx.fillStyle = this._colors.cursor; + this._renderBlurCursor(terminal, terminal.buffer.x, viewportRelativeCursorY, charData); + this._ctx.restore(); + this._state.x = terminal.buffer.x; + this._state.y = viewportRelativeCursorY; + this._state.isFocused = false; + this._state.style = terminal.options.cursorStyle; + this._state.width = charData[Buffer_1.CHAR_DATA_WIDTH_INDEX]; + return; + } + if (this._cursorBlinkStateManager && !this._cursorBlinkStateManager.isCursorVisible) { + this._clearCursor(); + return; + } + if (this._state) { + if (this._state.x === terminal.buffer.x && + this._state.y === viewportRelativeCursorY && + this._state.isFocused === terminal.isFocused && + this._state.style === terminal.options.cursorStyle && + this._state.width === charData[Buffer_1.CHAR_DATA_WIDTH_INDEX]) { + return; + } + this._clearCursor(); + } + this._ctx.save(); + this._cursorRenderers[terminal.options.cursorStyle || 'block'](terminal, terminal.buffer.x, viewportRelativeCursorY, charData); + this._ctx.restore(); + this._state.x = terminal.buffer.x; + this._state.y = viewportRelativeCursorY; + this._state.isFocused = false; + this._state.style = terminal.options.cursorStyle; + this._state.width = charData[Buffer_1.CHAR_DATA_WIDTH_INDEX]; + }; + CursorRenderLayer.prototype._clearCursor = function () { + if (this._state) { + this.clearCells(this._state.x, this._state.y, this._state.width, 1); + this._state = { + x: null, + y: null, + isFocused: null, + style: null, + width: null, + }; + } + }; + CursorRenderLayer.prototype._renderBarCursor = function (terminal, x, y, charData) { + this._ctx.save(); + this._ctx.fillStyle = this._colors.cursor; + this.fillLeftLineAtCell(x, y); + this._ctx.restore(); + }; + CursorRenderLayer.prototype._renderBlockCursor = function (terminal, x, y, charData) { + this._ctx.save(); + this._ctx.fillStyle = this._colors.cursor; + this.fillCells(x, y, charData[Buffer_1.CHAR_DATA_WIDTH_INDEX], 1); + this._ctx.fillStyle = this._colors.cursorAccent; + this.fillCharTrueColor(terminal, charData, x, y); + this._ctx.restore(); + }; + CursorRenderLayer.prototype._renderUnderlineCursor = function (terminal, x, y, charData) { + this._ctx.save(); + this._ctx.fillStyle = this._colors.cursor; + this.fillBottomLineAtCells(x, y); + this._ctx.restore(); + }; + CursorRenderLayer.prototype._renderBlurCursor = function (terminal, x, y, charData) { + this._ctx.save(); + this._ctx.strokeStyle = this._colors.cursor; + this.strokeRectAtCell(x, y, charData[Buffer_1.CHAR_DATA_WIDTH_INDEX], 1); + this._ctx.restore(); + }; + return CursorRenderLayer; +}(BaseRenderLayer_1.BaseRenderLayer)); +exports.CursorRenderLayer = CursorRenderLayer; +var CursorBlinkStateManager = (function () { + function CursorBlinkStateManager(terminal, renderCallback) { + this.renderCallback = renderCallback; + this.isCursorVisible = true; + if (terminal.isFocused) { + this._restartInterval(); + } + } + Object.defineProperty(CursorBlinkStateManager.prototype, "isPaused", { + get: function () { return !(this._blinkStartTimeout || this._blinkInterval); }, + enumerable: true, + configurable: true + }); + CursorBlinkStateManager.prototype.dispose = function () { + if (this._blinkInterval) { + window.clearInterval(this._blinkInterval); + this._blinkInterval = null; + } + if (this._blinkStartTimeout) { + window.clearTimeout(this._blinkStartTimeout); + this._blinkStartTimeout = null; + } + if (this._animationFrame) { + window.cancelAnimationFrame(this._animationFrame); + this._animationFrame = null; + } + }; + CursorBlinkStateManager.prototype.restartBlinkAnimation = function (terminal) { + var _this = this; + if (this.isPaused) { + return; + } + this._animationTimeRestarted = Date.now(); + this.isCursorVisible = true; + if (!this._animationFrame) { + this._animationFrame = window.requestAnimationFrame(function () { + _this.renderCallback(); + _this._animationFrame = null; + }); + } + }; + CursorBlinkStateManager.prototype._restartInterval = function (timeToStart) { + var _this = this; + if (timeToStart === void 0) { timeToStart = BLINK_INTERVAL; } + if (this._blinkInterval) { + window.clearInterval(this._blinkInterval); + } + this._blinkStartTimeout = setTimeout(function () { + if (_this._animationTimeRestarted) { + var time = BLINK_INTERVAL - (Date.now() - _this._animationTimeRestarted); + _this._animationTimeRestarted = null; + if (time > 0) { + _this._restartInterval(time); + return; + } + } + _this.isCursorVisible = false; + _this._animationFrame = window.requestAnimationFrame(function () { + _this.renderCallback(); + _this._animationFrame = null; + }); + _this._blinkInterval = setInterval(function () { + if (_this._animationTimeRestarted) { + var time = BLINK_INTERVAL - (Date.now() - _this._animationTimeRestarted); + _this._animationTimeRestarted = null; + _this._restartInterval(time); + return; + } + _this.isCursorVisible = !_this.isCursorVisible; + _this._animationFrame = window.requestAnimationFrame(function () { + _this.renderCallback(); + _this._animationFrame = null; + }); + }, BLINK_INTERVAL); + }, timeToStart); + }; + CursorBlinkStateManager.prototype.pause = function () { + this.isCursorVisible = true; + if (this._blinkInterval) { + window.clearInterval(this._blinkInterval); + this._blinkInterval = null; + } + if (this._blinkStartTimeout) { + window.clearTimeout(this._blinkStartTimeout); + this._blinkStartTimeout = null; + } + if (this._animationFrame) { + window.cancelAnimationFrame(this._animationFrame); + this._animationFrame = null; + } + }; + CursorBlinkStateManager.prototype.resume = function (terminal) { + this._animationTimeRestarted = null; + this._restartInterval(); + this.restartBlinkAnimation(terminal); + }; + return CursorBlinkStateManager; +}()); + + + +},{"../Buffer":1,"./BaseRenderLayer":18}],22:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var GridCache = (function () { + function GridCache() { + this.cache = []; + } + GridCache.prototype.resize = function (width, height) { + for (var x = 0; x < width; x++) { + if (this.cache.length <= x) { + this.cache.push([]); + } + for (var y = this.cache[x].length; y < height; y++) { + this.cache[x].push(null); + } + this.cache[x].length = height; + } + this.cache.length = width; + }; + GridCache.prototype.clear = function () { + for (var x = 0; x < this.cache.length; x++) { + for (var y = 0; y < this.cache[x].length; y++) { + this.cache[x][y] = null; + } + } + }; + return GridCache; +}()); +exports.GridCache = GridCache; + + + +},{}],23:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var BaseRenderLayer_1 = require("./BaseRenderLayer"); +var Types_1 = require("../Types"); +var LinkRenderLayer = (function (_super) { + __extends(LinkRenderLayer, _super); + function LinkRenderLayer(container, zIndex, colors, terminal) { + var _this = _super.call(this, container, 'link', zIndex, true, colors) || this; + _this._state = null; + terminal.linkifier.on(Types_1.LinkHoverEventTypes.HOVER, function (e) { return _this._onLinkHover(e); }); + terminal.linkifier.on(Types_1.LinkHoverEventTypes.LEAVE, function (e) { return _this._onLinkLeave(e); }); + return _this; + } + LinkRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) { + _super.prototype.resize.call(this, terminal, dim, charSizeChanged); + this._state = null; + }; + LinkRenderLayer.prototype.reset = function (terminal) { + this._clearCurrentLink(); + }; + LinkRenderLayer.prototype._clearCurrentLink = function () { + if (this._state) { + this.clearCells(this._state.x, this._state.y, this._state.length, 1); + this._state = null; + } + }; + LinkRenderLayer.prototype._onLinkHover = function (e) { + this._ctx.fillStyle = this._colors.foreground; + this.fillBottomLineAtCells(e.x, e.y, e.length); + this._state = e; + }; + LinkRenderLayer.prototype._onLinkLeave = function (e) { + this._clearCurrentLink(); + }; + return LinkRenderLayer; +}(BaseRenderLayer_1.BaseRenderLayer)); +exports.LinkRenderLayer = LinkRenderLayer; + + + +},{"../Types":14,"./BaseRenderLayer":18}],24:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var TextRenderLayer_1 = require("./TextRenderLayer"); +var SelectionRenderLayer_1 = require("./SelectionRenderLayer"); +var CursorRenderLayer_1 = require("./CursorRenderLayer"); +var ColorManager_1 = require("./ColorManager"); +var LinkRenderLayer_1 = require("./LinkRenderLayer"); +var EventEmitter_1 = require("../EventEmitter"); +var ScreenDprMonitor_1 = require("../utils/ScreenDprMonitor"); +var Renderer = (function (_super) { + __extends(Renderer, _super); + function Renderer(_terminal, theme) { + var _this = _super.call(this) || this; + _this._terminal = _terminal; + _this._refreshRowsQueue = []; + _this._refreshAnimationFrame = null; + _this._isPaused = false; + _this._needsFullRefresh = false; + _this.colorManager = new ColorManager_1.ColorManager(); + if (theme) { + _this.colorManager.setTheme(theme); + } + _this._renderLayers = [ + new TextRenderLayer_1.TextRenderLayer(_this._terminal.element, 0, _this.colorManager.colors, _this._terminal.options.allowTransparency), + new SelectionRenderLayer_1.SelectionRenderLayer(_this._terminal.element, 1, _this.colorManager.colors), + new LinkRenderLayer_1.LinkRenderLayer(_this._terminal.element, 2, _this.colorManager.colors, _this._terminal), + new CursorRenderLayer_1.CursorRenderLayer(_this._terminal.element, 3, _this.colorManager.colors) + ]; + _this.dimensions = { + scaledCharWidth: null, + scaledCharHeight: null, + scaledCellWidth: null, + scaledCellHeight: null, + scaledCharLeft: null, + scaledCharTop: null, + scaledCanvasWidth: null, + scaledCanvasHeight: null, + canvasWidth: null, + canvasHeight: null, + actualCellWidth: null, + actualCellHeight: null + }; + _this._devicePixelRatio = window.devicePixelRatio; + _this._updateDimensions(); + _this._screenDprMonitor = new ScreenDprMonitor_1.ScreenDprMonitor(); + _this._screenDprMonitor.setListener(function () { return _this.onWindowResize(window.devicePixelRatio); }); + if ('IntersectionObserver' in window) { + var observer = new IntersectionObserver(function (e) { return _this.onIntersectionChange(e[0]); }, { threshold: 0 }); + observer.observe(_this._terminal.element); + } + return _this; + } + Renderer.prototype.onIntersectionChange = function (entry) { + this._isPaused = entry.intersectionRatio === 0; + if (!this._isPaused && this._needsFullRefresh) { + this._terminal.refresh(0, this._terminal.rows - 1); + } + }; + Renderer.prototype.onWindowResize = function (devicePixelRatio) { + if (this._devicePixelRatio !== devicePixelRatio) { + this._devicePixelRatio = devicePixelRatio; + this.onResize(this._terminal.cols, this._terminal.rows, true); + } + }; + Renderer.prototype.setTheme = function (theme) { + var _this = this; + this.colorManager.setTheme(theme); + this._renderLayers.forEach(function (l) { + l.onThemeChanged(_this._terminal, _this.colorManager.colors); + l.reset(_this._terminal); + }); + if (this._isPaused) { + this._needsFullRefresh = true; + } + else { + this._terminal.refresh(0, this._terminal.rows - 1); + } + return this.colorManager.colors; + }; + Renderer.prototype.onResize = function (cols, rows, didCharSizeChange) { + var _this = this; + this._updateDimensions(); + this._renderLayers.forEach(function (l) { return l.resize(_this._terminal, _this.dimensions, didCharSizeChange); }); + if (this._isPaused) { + this._needsFullRefresh = true; + } + else { + this._terminal.refresh(0, this._terminal.rows - 1); + } + this.emit('resize', { + width: this.dimensions.canvasWidth, + height: this.dimensions.canvasHeight + }); + }; + Renderer.prototype.onCharSizeChanged = function () { + this.onResize(this._terminal.cols, this._terminal.rows, true); + }; + Renderer.prototype.onBlur = function () { + var _this = this; + this._runOperation(function (l) { return l.onBlur(_this._terminal); }); + }; + Renderer.prototype.onFocus = function () { + var _this = this; + this._runOperation(function (l) { return l.onFocus(_this._terminal); }); + }; + Renderer.prototype.onSelectionChanged = function (start, end) { + var _this = this; + this._runOperation(function (l) { return l.onSelectionChanged(_this._terminal, start, end); }); + }; + Renderer.prototype.onCursorMove = function () { + var _this = this; + this._runOperation(function (l) { return l.onCursorMove(_this._terminal); }); + }; + Renderer.prototype.onOptionsChanged = function () { + var _this = this; + this._runOperation(function (l) { return l.onOptionsChanged(_this._terminal); }); + }; + Renderer.prototype.clear = function () { + var _this = this; + this._runOperation(function (l) { return l.reset(_this._terminal); }); + }; + Renderer.prototype._runOperation = function (operation) { + if (this._isPaused) { + this._needsFullRefresh = true; + } + else { + this._renderLayers.forEach(function (l) { return operation(l); }); + } + }; + Renderer.prototype.queueRefresh = function (start, end) { + if (this._isPaused) { + this._needsFullRefresh = true; + return; + } + this._refreshRowsQueue.push({ start: start, end: end }); + if (!this._refreshAnimationFrame) { + this._refreshAnimationFrame = window.requestAnimationFrame(this._refreshLoop.bind(this)); + } + }; + Renderer.prototype._refreshLoop = function () { + var _this = this; + var start; + var end; + if (this._refreshRowsQueue.length > 4) { + start = 0; + end = this._terminal.rows - 1; + } + else { + start = this._refreshRowsQueue[0].start; + end = this._refreshRowsQueue[0].end; + for (var i = 1; i < this._refreshRowsQueue.length; i++) { + if (this._refreshRowsQueue[i].start < start) { + start = this._refreshRowsQueue[i].start; + } + if (this._refreshRowsQueue[i].end > end) { + end = this._refreshRowsQueue[i].end; + } + } + } + this._refreshRowsQueue = []; + this._refreshAnimationFrame = null; + start = Math.max(start, 0); + end = Math.min(end, this._terminal.rows - 1); + this._renderLayers.forEach(function (l) { return l.onGridChanged(_this._terminal, start, end); }); + this._terminal.emit('refresh', { start: start, end: end }); + }; + Renderer.prototype._updateDimensions = function () { + if (!this._terminal.charMeasure.width || !this._terminal.charMeasure.height) { + return; + } + this.dimensions.scaledCharWidth = Math.floor(this._terminal.charMeasure.width * window.devicePixelRatio); + this.dimensions.scaledCharHeight = Math.ceil(this._terminal.charMeasure.height * window.devicePixelRatio); + this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._terminal.options.lineHeight); + this.dimensions.scaledCharTop = this._terminal.options.lineHeight === 1 ? 0 : Math.round((this.dimensions.scaledCellHeight - this.dimensions.scaledCharHeight) / 2); + this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._terminal.options.letterSpacing); + this.dimensions.scaledCharLeft = Math.floor(this._terminal.options.letterSpacing / 2); + this.dimensions.scaledCanvasHeight = this._terminal.rows * this.dimensions.scaledCellHeight; + this.dimensions.scaledCanvasWidth = this._terminal.cols * this.dimensions.scaledCellWidth; + this.dimensions.canvasHeight = Math.round(this.dimensions.scaledCanvasHeight / window.devicePixelRatio); + this.dimensions.canvasWidth = Math.round(this.dimensions.scaledCanvasWidth / window.devicePixelRatio); + this.dimensions.actualCellHeight = this.dimensions.canvasHeight / this._terminal.rows; + this.dimensions.actualCellWidth = this.dimensions.canvasWidth / this._terminal.cols; + }; + return Renderer; +}(EventEmitter_1.EventEmitter)); +exports.Renderer = Renderer; + + + +},{"../EventEmitter":7,"../utils/ScreenDprMonitor":33,"./ColorManager":20,"./CursorRenderLayer":21,"./LinkRenderLayer":23,"./SelectionRenderLayer":25,"./TextRenderLayer":26}],25:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var BaseRenderLayer_1 = require("./BaseRenderLayer"); +var SelectionRenderLayer = (function (_super) { + __extends(SelectionRenderLayer, _super); + function SelectionRenderLayer(container, zIndex, colors) { + var _this = _super.call(this, container, 'selection', zIndex, true, colors) || this; + _this._state = { + start: null, + end: null + }; + return _this; + } + SelectionRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) { + _super.prototype.resize.call(this, terminal, dim, charSizeChanged); + this._state = { + start: null, + end: null + }; + }; + SelectionRenderLayer.prototype.reset = function (terminal) { + if (this._state.start && this._state.end) { + this._state = { + start: null, + end: null + }; + this.clearAll(); + } + }; + SelectionRenderLayer.prototype.onSelectionChanged = function (terminal, start, end) { + if (this._state.start === start || this._state.end === end) { + return; + } + this.clearAll(); + if (!start || !end) { + return; + } + var viewportStartRow = start[1] - terminal.buffer.ydisp; + var viewportEndRow = end[1] - terminal.buffer.ydisp; + var viewportCappedStartRow = Math.max(viewportStartRow, 0); + var viewportCappedEndRow = Math.min(viewportEndRow, terminal.rows - 1); + if (viewportCappedStartRow >= terminal.rows || viewportCappedEndRow < 0) { + return; + } + var startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0; + var startRowEndCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : terminal.cols; + this._ctx.fillStyle = this._colors.selection; + this.fillCells(startCol, viewportCappedStartRow, startRowEndCol - startCol, 1); + var middleRowsCount = Math.max(viewportCappedEndRow - viewportCappedStartRow - 1, 0); + this.fillCells(0, viewportCappedStartRow + 1, terminal.cols, middleRowsCount); + if (viewportCappedStartRow !== viewportCappedEndRow) { + var endCol = viewportEndRow === viewportCappedEndRow ? end[0] : terminal.cols; + this.fillCells(0, viewportCappedEndRow, endCol, 1); + } + this._state.start = [start[0], start[1]]; + this._state.end = [end[0], end[1]]; + }; + return SelectionRenderLayer; +}(BaseRenderLayer_1.BaseRenderLayer)); +exports.SelectionRenderLayer = SelectionRenderLayer; + + + +},{"./BaseRenderLayer":18}],26:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var Buffer_1 = require("../Buffer"); +var Types_1 = require("./Types"); +var GridCache_1 = require("./GridCache"); +var BaseRenderLayer_1 = require("./BaseRenderLayer"); +var OVERLAP_OWNED_CHAR_DATA = [null, '', 0, -1]; +var TextRenderLayer = (function (_super) { + __extends(TextRenderLayer, _super); + function TextRenderLayer(container, zIndex, colors, alpha) { + var _this = _super.call(this, container, 'text', zIndex, alpha, colors) || this; + _this._characterOverlapCache = {}; + _this._state = new GridCache_1.GridCache(); + return _this; + } + TextRenderLayer.prototype.resize = function (terminal, dim, charSizeChanged) { + _super.prototype.resize.call(this, terminal, dim, charSizeChanged); + var terminalFont = terminal.options.fontSize * window.devicePixelRatio + "px " + terminal.options.fontFamily; + if (this._characterWidth !== dim.scaledCharWidth || this._characterFont !== terminalFont) { + this._characterWidth = dim.scaledCharWidth; + this._characterFont = terminalFont; + this._characterOverlapCache = {}; + } + this._state.clear(); + this._state.resize(terminal.cols, terminal.rows); + }; + TextRenderLayer.prototype.reset = function (terminal) { + this._state.clear(); + this.clearAll(); + }; + TextRenderLayer.prototype.onGridChanged = function (terminal, startRow, endRow) { + if (this._state.cache.length === 0) { + return; + } + for (var y = startRow; y <= endRow; y++) { + var row = y + terminal.buffer.ydisp; + var line = terminal.buffer.lines.get(row); + this.clearCells(0, y, terminal.cols, 1); + for (var x = 0; x < terminal.cols; x++) { + var charData = line[x]; + var code = charData[Buffer_1.CHAR_DATA_CODE_INDEX]; + var char = charData[Buffer_1.CHAR_DATA_CHAR_INDEX]; + var attr = charData[Buffer_1.CHAR_DATA_ATTR_INDEX]; + var width = charData[Buffer_1.CHAR_DATA_WIDTH_INDEX]; + if (width === 0) { + continue; + } + if (code === 32) { + if (x > 0) { + var previousChar = line[x - 1]; + if (this._isOverlapping(previousChar)) { + continue; + } + } + } + var flags = attr >> 18; + var bg = attr & 0x1ff; + var isDefaultBackground = bg >= 256; + var isInvisible = flags & Types_1.FLAGS.INVISIBLE; + var isInverted = flags & Types_1.FLAGS.INVERSE; + if (!code || (code === 32 && isDefaultBackground && !isInverted) || isInvisible) { + continue; + } + if (width !== 0 && this._isOverlapping(charData)) { + if (x < line.length - 1 && line[x + 1][Buffer_1.CHAR_DATA_CODE_INDEX] === 32) { + width = 2; + } + } + var fg = (attr >> 9) & 0x1ff; + if (isInverted) { + var temp = bg; + bg = fg; + fg = temp; + if (fg === 256) { + fg = BaseRenderLayer_1.INVERTED_DEFAULT_COLOR; + } + if (bg === 257) { + bg = BaseRenderLayer_1.INVERTED_DEFAULT_COLOR; + } + } + if (width === 2) { + } + if (bg < 256) { + this._ctx.save(); + this._ctx.fillStyle = (bg === BaseRenderLayer_1.INVERTED_DEFAULT_COLOR ? this._colors.foreground : this._colors.ansi[bg]); + this.fillCells(x, y, width, 1); + this._ctx.restore(); + } + this._ctx.save(); + if (flags & Types_1.FLAGS.BOLD) { + this._ctx.font = "bold " + this._ctx.font; + if (fg < 8) { + fg += 8; + } + } + if (flags & Types_1.FLAGS.UNDERLINE) { + if (fg === BaseRenderLayer_1.INVERTED_DEFAULT_COLOR) { + this._ctx.fillStyle = this._colors.background; + } + else if (fg < 256) { + this._ctx.fillStyle = this._colors.ansi[fg]; + } + else { + this._ctx.fillStyle = this._colors.foreground; + } + this.fillBottomLineAtCells(x, y); + } + this.drawChar(terminal, char, code, width, x, y, fg, bg, !!(flags & Types_1.FLAGS.BOLD), !!(flags & Types_1.FLAGS.DIM)); + this._ctx.restore(); + } + } + }; + TextRenderLayer.prototype._isOverlapping = function (charData) { + if (charData[Buffer_1.CHAR_DATA_WIDTH_INDEX] !== 1) { + return false; + } + var code = charData[Buffer_1.CHAR_DATA_CODE_INDEX]; + if (code < 256) { + return false; + } + var char = charData[Buffer_1.CHAR_DATA_CHAR_INDEX]; + if (this._characterOverlapCache.hasOwnProperty(char)) { + return this._characterOverlapCache[char]; + } + this._ctx.save(); + this._ctx.font = this._characterFont; + var overlaps = Math.floor(this._ctx.measureText(char).width) > this._characterWidth; + this._ctx.restore(); + this._characterOverlapCache[char] = overlaps; + return overlaps; + }; + TextRenderLayer.prototype._clearChar = function (x, y) { + var colsToClear = 1; + var state = this._state.cache[x][y]; + if (state && state[Buffer_1.CHAR_DATA_WIDTH_INDEX] === 2) { + colsToClear = 2; + } + this.clearCells(x, y, colsToClear, 1); + }; + return TextRenderLayer; +}(BaseRenderLayer_1.BaseRenderLayer)); +exports.TextRenderLayer = TextRenderLayer; + + + +},{"../Buffer":1,"./BaseRenderLayer":18,"./GridCache":22,"./Types":27}],27:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var FLAGS; +(function (FLAGS) { + FLAGS[FLAGS["BOLD"] = 1] = "BOLD"; + FLAGS[FLAGS["UNDERLINE"] = 2] = "UNDERLINE"; + FLAGS[FLAGS["BLINK"] = 4] = "BLINK"; + FLAGS[FLAGS["INVERSE"] = 8] = "INVERSE"; + FLAGS[FLAGS["INVISIBLE"] = 16] = "INVISIBLE"; + FLAGS[FLAGS["DIM"] = 32] = "DIM"; +})(FLAGS = exports.FLAGS || (exports.FLAGS = {})); +; + + + +},{}],28:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Generic_1 = require("./Generic"); +var isNode = (typeof navigator === 'undefined') ? true : false; +var userAgent = (isNode) ? 'node' : navigator.userAgent; +var platform = (isNode) ? 'node' : navigator.platform; +exports.isFirefox = !!~userAgent.indexOf('Firefox'); +exports.isMSIE = !!~userAgent.indexOf('MSIE') || !!~userAgent.indexOf('Trident'); +exports.isMac = Generic_1.contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform); +exports.isIpad = platform === 'iPad'; +exports.isIphone = platform === 'iPhone'; +exports.isMSWindows = Generic_1.contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform); +exports.isLinux = platform.indexOf('Linux') >= 0; + + + +},{"./Generic":31}],29:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var EventEmitter_1 = require("../EventEmitter"); +var CharMeasure = (function (_super) { + __extends(CharMeasure, _super); + function CharMeasure(document, parentElement) { + var _this = _super.call(this) || this; + _this._document = document; + _this._parentElement = parentElement; + _this._measureElement = _this._document.createElement('span'); + _this._measureElement.style.position = 'absolute'; + _this._measureElement.style.top = '0'; + _this._measureElement.style.left = '-9999em'; + _this._measureElement.style.lineHeight = 'normal'; + _this._measureElement.textContent = 'W'; + _this._measureElement.setAttribute('aria-hidden', 'true'); + _this._parentElement.appendChild(_this._measureElement); + return _this; + } + Object.defineProperty(CharMeasure.prototype, "width", { + get: function () { + return this._width; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CharMeasure.prototype, "height", { + get: function () { + return this._height; + }, + enumerable: true, + configurable: true + }); + CharMeasure.prototype.measure = function (options) { + this._measureElement.style.fontFamily = options.fontFamily; + this._measureElement.style.fontSize = options.fontSize + "px"; + var geometry = this._measureElement.getBoundingClientRect(); + if (geometry.width === 0 || geometry.height === 0) { + return; + } + if (this._width !== geometry.width || this._height !== geometry.height) { + this._width = geometry.width; + this._height = Math.ceil(geometry.height); + this.emit('charsizechanged'); + } + }; + return CharMeasure; +}(EventEmitter_1.EventEmitter)); +exports.CharMeasure = CharMeasure; + + + +},{"../EventEmitter":7}],30:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var EventEmitter_1 = require("../EventEmitter"); +var CircularList = (function (_super) { + __extends(CircularList, _super); + function CircularList(_maxLength) { + var _this = _super.call(this) || this; + _this._maxLength = _maxLength; + _this._array = new Array(_this._maxLength); + _this._startIndex = 0; + _this._length = 0; + return _this; + } + Object.defineProperty(CircularList.prototype, "maxLength", { + get: function () { + return this._maxLength; + }, + set: function (newMaxLength) { + if (this._maxLength === newMaxLength) { + return; + } + var newArray = new Array(newMaxLength); + for (var i = 0; i < Math.min(newMaxLength, this.length); i++) { + newArray[i] = this._array[this._getCyclicIndex(i)]; + } + this._array = newArray; + this._maxLength = newMaxLength; + this._startIndex = 0; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CircularList.prototype, "length", { + get: function () { + return this._length; + }, + set: function (newLength) { + if (newLength > this._length) { + for (var i = this._length; i < newLength; i++) { + this._array[i] = undefined; + } + } + this._length = newLength; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(CircularList.prototype, "forEach", { + get: function () { + var _this = this; + return function (callbackfn) { + var i = 0; + var length = _this.length; + for (var i_1 = 0; i_1 < length; i_1++) { + callbackfn(_this.get(i_1), i_1); + } + }; + }, + enumerable: true, + configurable: true + }); + CircularList.prototype.get = function (index) { + return this._array[this._getCyclicIndex(index)]; + }; + CircularList.prototype.set = function (index, value) { + this._array[this._getCyclicIndex(index)] = value; + }; + CircularList.prototype.push = function (value) { + this._array[this._getCyclicIndex(this._length)] = value; + if (this._length === this._maxLength) { + this._startIndex++; + if (this._startIndex === this._maxLength) { + this._startIndex = 0; + } + this.emit('trim', 1); + } + else { + this._length++; + } + }; + CircularList.prototype.pop = function () { + return this._array[this._getCyclicIndex(this._length-- - 1)]; + }; + CircularList.prototype.splice = function (start, deleteCount) { + var items = []; + for (var _i = 2; _i < arguments.length; _i++) { + items[_i - 2] = arguments[_i]; + } + if (deleteCount) { + for (var i = start; i < this._length - deleteCount; i++) { + this._array[this._getCyclicIndex(i)] = this._array[this._getCyclicIndex(i + deleteCount)]; + } + this._length -= deleteCount; + } + if (items && items.length) { + for (var i = this._length - 1; i >= start; i--) { + this._array[this._getCyclicIndex(i + items.length)] = this._array[this._getCyclicIndex(i)]; + } + for (var i = 0; i < items.length; i++) { + this._array[this._getCyclicIndex(start + i)] = items[i]; + } + if (this._length + items.length > this.maxLength) { + var countToTrim = (this._length + items.length) - this.maxLength; + this._startIndex += countToTrim; + this._length = this.maxLength; + this.emit('trim', countToTrim); + } + else { + this._length += items.length; + } + } + }; + CircularList.prototype.trimStart = function (count) { + if (count > this._length) { + count = this._length; + } + this._startIndex += count; + this._length -= count; + this.emit('trim', count); + }; + CircularList.prototype.shiftElements = function (start, count, offset) { + if (count <= 0) { + return; + } + if (start < 0 || start >= this._length) { + throw new Error('start argument out of range'); + } + if (start + offset < 0) { + throw new Error('Cannot shift elements in list beyond index 0'); + } + if (offset > 0) { + for (var i = count - 1; i >= 0; i--) { + this.set(start + i + offset, this.get(start + i)); + } + var expandListBy = (start + count + offset) - this._length; + if (expandListBy > 0) { + this._length += expandListBy; + while (this._length > this.maxLength) { + this._length--; + this._startIndex++; + this.emit('trim', 1); + } + } + } + else { + for (var i = 0; i < count; i++) { + this.set(start + i + offset, this.get(start + i)); + } + } + }; + CircularList.prototype._getCyclicIndex = function (index) { + return (this._startIndex + index) % this.maxLength; + }; + return CircularList; +}(EventEmitter_1.EventEmitter)); +exports.CircularList = CircularList; + + + +},{"../EventEmitter":7}],31:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function contains(arr, el) { + return arr.indexOf(el) >= 0; +} +exports.contains = contains; +; + + + +},{}],32:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var MouseHelper = (function () { + function MouseHelper(_renderer) { + this._renderer = _renderer; + } + MouseHelper.getCoordsRelativeToElement = function (event, element) { + if (event.pageX == null) { + return null; + } + var originalElement = element; + var x = event.pageX; + var y = event.pageY; + while (element) { + x -= element.offsetLeft; + y -= element.offsetTop; + element = 'offsetParent' in element ? element.offsetParent : element.parentElement; + } + element = originalElement; + while (element && element !== element.ownerDocument.body) { + x += element.scrollLeft; + y += element.scrollTop; + element = element.parentElement; + } + return [x, y]; + }; + MouseHelper.prototype.getCoords = function (event, element, charMeasure, lineHeight, colCount, rowCount, isSelection) { + if (!charMeasure.width || !charMeasure.height) { + return null; + } + var coords = MouseHelper.getCoordsRelativeToElement(event, element); + if (!coords) { + return null; + } + coords[0] = Math.ceil((coords[0] + (isSelection ? this._renderer.dimensions.actualCellWidth / 2 : 0)) / this._renderer.dimensions.actualCellWidth); + coords[1] = Math.ceil(coords[1] / this._renderer.dimensions.actualCellHeight); + coords[0] = Math.min(Math.max(coords[0], 1), colCount + (isSelection ? 1 : 0)); + coords[1] = Math.min(Math.max(coords[1], 1), rowCount); + return coords; + }; + MouseHelper.prototype.getRawByteCoords = function (event, element, charMeasure, lineHeight, colCount, rowCount) { + var coords = this.getCoords(event, element, charMeasure, lineHeight, colCount, rowCount); + var x = coords[0]; + var y = coords[1]; + x += 32; + y += 32; + return { x: x, y: y }; + }; + return MouseHelper; +}()); +exports.MouseHelper = MouseHelper; + + + +},{}],33:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var ScreenDprMonitor = (function () { + function ScreenDprMonitor() { + } + ScreenDprMonitor.prototype.setListener = function (listener) { + var _this = this; + if (this._listener) { + this.clearListener(); + } + this._listener = listener; + this._outerListener = function () { + _this._listener(window.devicePixelRatio, _this._currentDevicePixelRatio); + _this._updateDpr(); + }; + this._updateDpr(); + }; + ScreenDprMonitor.prototype._updateDpr = function () { + if (this._resolutionMediaMatchList) { + this._resolutionMediaMatchList.removeListener(this._outerListener); + } + this._currentDevicePixelRatio = window.devicePixelRatio; + this._resolutionMediaMatchList = window.matchMedia("screen and (resolution: " + window.devicePixelRatio + "dppx)"); + this._resolutionMediaMatchList.addListener(this._outerListener); + }; + ScreenDprMonitor.prototype.clearListener = function () { + if (!this._listener) { + return; + } + this._resolutionMediaMatchList.removeListener(this._outerListener); + this._listener = null; + this._outerListener = null; + }; + return ScreenDprMonitor; +}()); +exports.ScreenDprMonitor = ScreenDprMonitor; + + + +},{}],34:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BellSound = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQBAADpAFgCwAMlBZoG/wdmCcoKRAypDQ8PbRDBEQQTOxRtFYcWlBePGIUZXhoiG88bcBz7HHIdzh0WHlMeZx51HmkeUx4WHs8dah0AHXwc3hs9G4saxRnyGBIYGBcQFv8U4RPAEoYRQBACD70NWwwHC6gJOwjWBloF7gOBAhABkf8b/qv8R/ve+Xf4Ife79W/0JfPZ8Z/wde9N7ijtE+wU6xvqM+lb6H7nw+YX5mrlxuQz5Mzje+Ma49fioeKD4nXiYeJy4pHitOL04j/jn+MN5IPkFOWs5U3mDefM55/ogOl36m7rdOyE7abuyu8D8Unyj/Pg9D/2qfcb+Yn6/vuK/Qj/lAAlAg=='; + + + +},{}],35:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Terminal_1 = require("./Terminal"); +module.exports = Terminal_1.Terminal; + + + +},{"./Terminal":13}]},{},[35])(35) +}); +//# sourceMappingURL=xterm.js.map + + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function attach(term, socket, bidirectional, buffered) { + bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; + term.socket = socket; + term._flushBuffer = function () { + term.write(term._attachSocketBuffer); + term._attachSocketBuffer = null; + }; + term._pushToBuffer = function (data) { + if (term._attachSocketBuffer) { + term._attachSocketBuffer += data; + } + else { + term._attachSocketBuffer = data; + setTimeout(term._flushBuffer, 10); + } + }; + var myTextDecoder; + term._getMessage = function (ev) { + var str; + if (typeof ev.data === "object") { + if (ev.data instanceof ArrayBuffer) { + if (!myTextDecoder) { + myTextDecoder = new TextDecoder(); + } + str = myTextDecoder.decode(ev.data); + } + else { + throw "TODO: handle Blob?"; + } + } + if (buffered) { + term._pushToBuffer(str || ev.data); + } + else { + term.write(str || ev.data); + } + }; + term._sendData = function (data) { + if (socket.readyState !== 1) { + return; + } + socket.send(data); + }; + socket.addEventListener('message', term._getMessage); + if (bidirectional) { + term.on('data', term._sendData); + } + socket.addEventListener('close', term.detach.bind(term, socket)); + socket.addEventListener('error', term.detach.bind(term, socket)); +} +exports.attach = attach; +; +function detach(term, socket) { + term.off('data', term._sendData); + socket = (typeof socket == 'undefined') ? term.socket : socket; + if (socket) { + socket.removeEventListener('message', term._getMessage); + } + delete term.socket; +} +exports.detach = detach; +; +function apply(terminalConstructor) { + terminalConstructor.prototype.attach = function (socket, bidirectional, buffered) { + return attach(this, socket, bidirectional, buffered); + }; + terminalConstructor.prototype.detach = function (socket) { + return detach(this, socket); + }; +} +exports.apply = apply; + +//# sourceMappingURL=attach.js.map + + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function proposeGeometry(term) { + if (!term.element.parentElement) { + return null; + } + var parentElementStyle = window.getComputedStyle(term.element.parentElement); + var parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')); + var parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17); + var elementStyle = window.getComputedStyle(term.element); + var elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')); + var elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')); + var availableHeight = parentElementHeight - elementPaddingVer; + var availableWidth = parentElementWidth - elementPaddingHor; + var geometry = { + cols: Math.floor(availableWidth / term.renderer.dimensions.actualCellWidth), + rows: Math.floor(availableHeight / term.renderer.dimensions.actualCellHeight) + }; + return geometry; +} +exports.proposeGeometry = proposeGeometry; +; +function fit(term) { + var geometry = proposeGeometry(term); + if (geometry) { + if (term.rows !== geometry.rows || term.cols !== geometry.cols) { + term.renderer.clear(); + term.resize(geometry.cols, geometry.rows); + } + } +} +exports.fit = fit; +; +function apply(terminalConstructor) { + terminalConstructor.prototype.proposeGeometry = function () { + return proposeGeometry(this); + }; + terminalConstructor.prototype.fit = function () { + return fit(this); + }; +} +exports.apply = apply; + +//# sourceMappingURL=fit.js.map + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function winptyCompatInit(terminal) { + var isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].indexOf(navigator.platform) >= 0; + if (!isWindows) { + return; + } + terminal.on('linefeed', function () { + var line = terminal.buffer.lines.get(terminal.buffer.ybase + terminal.buffer.y - 1); + var lastChar = line[terminal.cols - 1]; + if (lastChar[3] !== 32) { + var nextLine = terminal.buffer.lines.get(terminal.buffer.ybase + terminal.buffer.y); + nextLine.isWrapped = true; + } + }); +} +exports.winptyCompatInit = winptyCompatInit; +function apply(terminalConstructor) { + terminalConstructor.prototype.winptyCompatInit = function () { + winptyCompatInit(this); + }; +} +exports.apply = apply; + +//# sourceMappingURL=winptyCompat.js.map + + +/***/ }) +/******/ ]); \ No newline at end of file diff --git a/FluentTerminal.SystemTray/Client/index.html b/FluentTerminal.SystemTray/Client/index.html new file mode 100644 index 0000000..196ede2 --- /dev/null +++ b/FluentTerminal.SystemTray/Client/index.html @@ -0,0 +1,12 @@ + + + + + + + + +
+ + + \ No newline at end of file diff --git a/FluentTerminal.SystemTray/Client/style.css b/FluentTerminal.SystemTray/Client/style.css new file mode 100644 index 0000000..41f437c --- /dev/null +++ b/FluentTerminal.SystemTray/Client/style.css @@ -0,0 +1,24 @@ +* { + margin: 0; +} + +html { + -ms-overflow-style: none; + background: transparent; + height: 100%; + } + +body { + background: transparent; + height: 100%; +} + +#terminal-container { + width: 100%; + height: 100%; + margin: 0; +} + +.terminal { + background: transparent !important; +} diff --git a/FluentTerminal.SystemTray/Client/xterm.css b/FluentTerminal.SystemTray/Client/xterm.css new file mode 100644 index 0000000..b3ee50f --- /dev/null +++ b/FluentTerminal.SystemTray/Client/xterm.css @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) + * https://github.com/chjj/term.js + * @license MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Originally forked from (with the author's permission): + * Fabrice Bellard's javascript vt100 for jslinux: + * http://bellard.org/jslinux/ + * Copyright (c) 2011 Fabrice Bellard + * The original design remains. The terminal itself + * has been extended to include xterm CSI codes, among + * other features. + */ + +/** + * Default styles for xterm.js + */ + +.xterm { + font-family: courier-new, courier, monospace; + font-feature-settings: "liga" 0; + position: relative; + user-select: none; + -ms-user-select: none; + -webkit-user-select: none; +} + +.xterm.focus, +.xterm:focus { + outline: none; +} + +.xterm .xterm-helpers { + position: absolute; + top: 0; + /** + * The z-index of the helpers must be higher than the canvases in order for + * IMEs to appear on top. + */ + z-index: 10; +} + +.xterm .xterm-helper-textarea { + /* + * HACK: to fix IE's blinking cursor + * Move textarea out of the screen to the far left, so that the cursor is not visible. + */ + position: absolute; + opacity: 0; + left: -9999em; + top: 0; + width: 0; + height: 0; + z-index: -10; + /** Prevent wrapping so the IME appears against the textarea at the correct position */ + white-space: nowrap; + overflow: hidden; + resize: none; +} + +.xterm .composition-view { + /* TODO: Composition position got messed up somewhere */ + background: #000; + color: #FFF; + display: none; + position: absolute; + white-space: nowrap; + z-index: 1; +} + +.xterm .composition-view.active { + display: block; +} + +.xterm .xterm-viewport { + /* On OS X this is required in order for the scroll bar to appear fully opaque */ + background-color: #000; + overflow-y: scroll; + cursor: default; +} + +.xterm canvas { + position: absolute; + left: 0; + top: 0; +} + +.xterm .xterm-scroll-area { + visibility: hidden; +} + +.xterm .xterm-char-measure-element { + display: inline-block; + visibility: hidden; + position: absolute; + left: -9999em; +} + +.xterm.enable-mouse-events { + /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */ + cursor: default; +} + +.xterm:not(.enable-mouse-events) { + cursor: text; +} diff --git a/FluentTerminal.SystemTray/Controllers/TerminalsController.cs b/FluentTerminal.SystemTray/Controllers/TerminalsController.cs new file mode 100644 index 0000000..198cf0c --- /dev/null +++ b/FluentTerminal.SystemTray/Controllers/TerminalsController.cs @@ -0,0 +1,33 @@ +using FluentTerminal.SystemTray.DataTransferObjects; +using FluentTerminal.SystemTray.Services; +using System; +using System.Linq; +using System.Net.Http; +using System.Web.Http; + +namespace FluentTerminal.SystemTray.Controllers +{ + public class TerminalsController : ApiController + { + private TerminalsManager _terminalsManager; + + public TerminalsController(TerminalsManager terminalsManager) + { + _terminalsManager = terminalsManager ?? throw new ArgumentNullException(nameof(terminalsManager)); + } + + [HttpPost] + [Route("terminals")] + public string Post() + { + var cols = int.Parse(this.Request.GetQueryNameValuePairs().SingleOrDefault(q => q.Key == "cols").Value); + var rows = int.Parse(this.Request.GetQueryNameValuePairs().SingleOrDefault(q => q.Key == "rows").Value); + var options = new TerminalOptions + { + Columns = cols, + Rows = rows + }; + return _terminalsManager.CreateTerminal(options); + } + } +} diff --git a/FluentTerminal.SystemTray/DataTransferObjects/TerminalOptions.cs b/FluentTerminal.SystemTray/DataTransferObjects/TerminalOptions.cs new file mode 100644 index 0000000..16744e0 --- /dev/null +++ b/FluentTerminal.SystemTray/DataTransferObjects/TerminalOptions.cs @@ -0,0 +1,10 @@ +namespace FluentTerminal.SystemTray.DataTransferObjects +{ + public class TerminalOptions + { + public int Rows { get; set; } + public int Columns { get; set; } + public string PWD { get; set; } + public string ShellExecutable { get; set; } + } +} diff --git a/FluentTerminal.SystemTray/FluentTerminal.SystemTray.csproj b/FluentTerminal.SystemTray/FluentTerminal.SystemTray.csproj new file mode 100644 index 0000000..2af7c27 --- /dev/null +++ b/FluentTerminal.SystemTray/FluentTerminal.SystemTray.csproj @@ -0,0 +1,199 @@ + + + + + Debug + AnyCPU + {9EDDE318-0003-4553-B6F9-3FE5473563FD} + WinExe + FluentTerminal.SystemTray + FluentTerminal.SystemTray + v4.7 + 512 + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + app.manifest + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + true + + + + + + + False + ..\..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll + False + + + False + ..\..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.UI.Xaml.dll + False + + + + + + + + + + + + ..\..\..\..\..\..\..\Program Files (x86)\Windows Kits\10\UnionMetadata\Facade\Windows.WinMD + False + + + ..\..\..\..\..\..\..\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd + False + + + ..\..\..\..\..\..\..\Program Files (x86)\Windows Kits\10\References\10.0.15063.0\Windows.Foundation.UniversalApiContract\4.0.0.0\Windows.Foundation.UniversalApiContract.winmd + False + + + + + + + + + + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + 0.14.0.59 + + + 5.2.3 + + + 3.1.0 + + + 5.3.0 + + + 0.4.2 + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + + + + xcopy /y "$(ProjectDir)BinaryDependencies\$(PlatformName)" "$(ProjectDir)bin\$(PlatformName)\$(ConfigurationName)" +xcopy /y /s "$(ProjectDir)bin\$(PlatformName)\$(ConfigurationName)" "$(SolutionDir)FluentTerminal.App\Win32" + + + + xcopy /y "$(SolutionDir)FluentTerminal.Client\dist" "$(ProjectDir)Client" + + \ No newline at end of file diff --git a/FluentTerminal.SystemTray/LoopbackEnabler.cs b/FluentTerminal.SystemTray/LoopbackEnabler.cs new file mode 100644 index 0000000..985a5f5 --- /dev/null +++ b/FluentTerminal.SystemTray/LoopbackEnabler.cs @@ -0,0 +1,330 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace FluentTerminal.SystemTray +{ + public class LoopbackEnabler + { + //http://msdn.microsoft.com/en-us/library/windows/desktop/aa379595(v=vs.85).aspx + [StructLayoutAttribute(LayoutKind.Sequential)] + internal struct SID_AND_ATTRIBUTES + { + public IntPtr Sid; + public uint Attributes; + } + + [StructLayoutAttribute(LayoutKind.Sequential)] + internal struct INET_FIREWALL_AC_CAPABILITIES + { + public uint count; + public IntPtr capabilities; //SID_AND_ATTRIBUTES + } + + [StructLayoutAttribute(LayoutKind.Sequential)] + internal struct INET_FIREWALL_AC_BINARIES + { + public uint count; + public IntPtr binaries; + } + + [StructLayoutAttribute(LayoutKind.Sequential)] + internal struct INET_FIREWALL_APP_CONTAINER + { + internal IntPtr appContainerSid; + internal IntPtr userSid; + [MarshalAs(UnmanagedType.LPWStr)] + public string appContainerName; + [MarshalAs(UnmanagedType.LPWStr)] + public string displayName; + [MarshalAs(UnmanagedType.LPWStr)] + public string description; + internal INET_FIREWALL_AC_CAPABILITIES capabilities; + internal INET_FIREWALL_AC_BINARIES binaries; + [MarshalAs(UnmanagedType.LPWStr)] + public string workingDirectory; + [MarshalAs(UnmanagedType.LPWStr)] + public string packageFullName; + } + + + // Call this API to free the memory returned by the Enumeration API + [DllImport("FirewallAPI.dll")] + internal static extern void NetworkIsolationFreeAppContainers(IntPtr pACs); + + // Call this API to load the current list of LoopUtil-enabled AppContainers + [DllImport("FirewallAPI.dll")] + internal static extern uint NetworkIsolationGetAppContainerConfig(out uint pdwCntACs, out IntPtr appContainerSids); + + // Call this API to set the LoopUtil-exemption list + [DllImport("FirewallAPI.dll")] + private static extern uint NetworkIsolationSetAppContainerConfig(uint pdwCntACs, SID_AND_ATTRIBUTES[] appContainerSids); + + + // Use this API to convert a string SID into an actual SID + [DllImport("advapi32.dll", SetLastError = true)] + internal static extern bool ConvertStringSidToSid(string strSid, out IntPtr pSid); + + [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)] + static extern bool ConvertSidToStringSid( + [MarshalAs(UnmanagedType.LPArray)] byte[] pSID, + out IntPtr ptrSid); + + [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)] + static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid); + + // Use this API to convert a string reference (e.g. "@{blah.pri?ms-resource://whatever}") into a plain string + [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] + internal static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf); + + // Call this API to enumerate all of the AppContainers on the system + [DllImport("FirewallAPI.dll")] + internal static extern uint NetworkIsolationEnumAppContainers(uint Flags, out uint pdwCntPublicACs, out IntPtr ppACs); + // DWORD NetworkIsolationEnumAppContainers( + // _In_ DWORD Flags, + // _Out_ DWORD *pdwNumPublicAppCs, + // _Out_ PINET_FIREWALL_APP_CONTAINER *ppPublicAppCs + //); + + //http://msdn.microsoft.com/en-gb/library/windows/desktop/hh968116.aspx + enum NETISO_FLAG + { + NETISO_FLAG_FORCE_COMPUTE_BINARIES = 0x1, + NETISO_FLAG_MAX = 0x2 + } + + public class AppContainer + { + public String appContainerName { get; set; } + public String displayName { get; set; } + public String workingDirectory { get; set; } + public String StringSid { get; set; } + public List capabilities { get; set; } + public bool LoopUtil { get; set; } + + public AppContainer(String _appContainerName, String _displayName, String _workingDirectory, IntPtr _sid) + { + this.appContainerName = _appContainerName; + this.displayName = _displayName; + this.workingDirectory = _workingDirectory; + String tempSid; + ConvertSidToStringSid(_sid, out tempSid); + this.StringSid = tempSid; + } + } + + internal List _AppList; + internal List _AppListConfig; + public List Apps = new List(); + internal IntPtr _pACs; + + public LoopbackEnabler() + { + LoadApps(); + } + + public void EnableForApp(string appName) + { + var app = Apps.SingleOrDefault(a => a.displayName == appName); + + if (app != null) + { + app.LoopUtil = true; + SaveLoopbackState(); + } + } + + public void LoadApps() + { + Apps.Clear(); + _pACs = IntPtr.Zero; + //Full List of Apps + _AppList = PI_NetworkIsolationEnumAppContainers(); + //List of Apps that have LoopUtil enabled. + _AppListConfig = PI_NetworkIsolationGetAppContainerConfig(); + foreach (var PI_app in _AppList) + { + AppContainer app = new AppContainer(PI_app.appContainerName, PI_app.displayName, PI_app.workingDirectory, PI_app.appContainerSid); + + var app_capabilities = LoopbackEnabler.getCapabilites(PI_app.capabilities); + if (app_capabilities.Count > 0) + { + //var sid = new SecurityIdentifier(app_capabilities[0], 0); + + IntPtr arrayValue = IntPtr.Zero; + //var b = LoopUtil.ConvertStringSidToSid(app_capabilities[0].Sid, out arrayValue); + //string mysid; + //var b = LoopUtil.ConvertSidToStringSid(app_capabilities[0].Sid, out mysid); + } + app.LoopUtil = CheckLoopback(PI_app.appContainerSid); + Apps.Add(app); + } + } + private bool CheckLoopback(IntPtr intPtr) + { + foreach (SID_AND_ATTRIBUTES item in _AppListConfig) + { + string left, right; + ConvertSidToStringSid(item.Sid, out left); + ConvertSidToStringSid(intPtr, out right); + + if (left == right) + { + return true; + } + } + return false; + } + + private static List getCapabilites(INET_FIREWALL_AC_CAPABILITIES cap) + { + List mycap = new List(); + + IntPtr arrayValue = cap.capabilities; + + var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES)); + for (var i = 0; i < cap.count; i++) + { + var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES)); + mycap.Add(cur); + arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize)); + } + + return mycap; + + } + + private static List getContainerSID(INET_FIREWALL_AC_CAPABILITIES cap) + { + List mycap = new List(); + + IntPtr arrayValue = cap.capabilities; + + var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES)); + for (var i = 0; i < cap.count; i++) + { + var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES)); + mycap.Add(cur); + arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize)); + } + + return mycap; + + } + + private static List PI_NetworkIsolationGetAppContainerConfig() + { + + IntPtr arrayValue = IntPtr.Zero; + uint size = 0; + var list = new List(); + + // Pin down variables + GCHandle handle_pdwCntPublicACs = GCHandle.Alloc(size, GCHandleType.Pinned); + GCHandle handle_ppACs = GCHandle.Alloc(arrayValue, GCHandleType.Pinned); + + uint retval = NetworkIsolationGetAppContainerConfig(out size, out arrayValue); + + var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES)); + for (var i = 0; i < size; i++) + { + var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES)); + list.Add(cur); + arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize)); + } + + //release pinned variables. + handle_pdwCntPublicACs.Free(); + handle_ppACs.Free(); + + return list; + + + } + + private List PI_NetworkIsolationEnumAppContainers() + { + + IntPtr arrayValue = IntPtr.Zero; + uint size = 0; + var list = new List(); + + // Pin down variables + GCHandle handle_pdwCntPublicACs = GCHandle.Alloc(size, GCHandleType.Pinned); + GCHandle handle_ppACs = GCHandle.Alloc(arrayValue, GCHandleType.Pinned); + + //uint retval2 = NetworkIsolationGetAppContainerConfig( out size, out arrayValue); + + uint retval = NetworkIsolationEnumAppContainers((Int32)NETISO_FLAG.NETISO_FLAG_MAX, out size, out arrayValue); + _pACs = arrayValue; //store the pointer so it can be freed when we close the form + + var structSize = Marshal.SizeOf(typeof(INET_FIREWALL_APP_CONTAINER)); + for (var i = 0; i < size; i++) + { + var cur = (INET_FIREWALL_APP_CONTAINER)Marshal.PtrToStructure(arrayValue, typeof(INET_FIREWALL_APP_CONTAINER)); + list.Add(cur); + arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize)); + } + + //release pinned variables. + handle_pdwCntPublicACs.Free(); + handle_ppACs.Free(); + + return list; + + + } + + public bool SaveLoopbackState() + { + var countEnabled = CountEnabledLoopUtil(); + SID_AND_ATTRIBUTES[] arr = new SID_AND_ATTRIBUTES[countEnabled]; + int count = 0; + + for (int i = 0; i < Apps.Count; i++) + { + if (Apps[i].LoopUtil) + { + arr[count].Attributes = 0; + //TO DO: + IntPtr ptr; + ConvertStringSidToSid(Apps[i].StringSid, out ptr); + arr[count].Sid = ptr; + count++; + } + + } + + + if (NetworkIsolationSetAppContainerConfig((uint)countEnabled, arr) == 0) + { + return true; + } + else + { return false; } + + } + + private int CountEnabledLoopUtil() + { + var count = 0; + for (int i = 0; i < Apps.Count; i++) + { + if (Apps[i].LoopUtil) + { + count++; + } + + } + return count; + } + + public void FreeResources() + { + NetworkIsolationFreeAppContainers(_pACs); + } + + } +} diff --git a/FluentTerminal.SystemTray/Program.cs b/FluentTerminal.SystemTray/Program.cs new file mode 100644 index 0000000..60bb281 --- /dev/null +++ b/FluentTerminal.SystemTray/Program.cs @@ -0,0 +1,36 @@ +using System; +using System.Threading; +using System.Windows.Forms; +using Microsoft.Owin.Hosting; +using Windows.ApplicationModel; + +namespace FluentTerminal.SystemTray +{ + public static class Program + { + private const string MutexName = "FluentTerminalMutex"; + + [STAThread] + public static void Main() + { + if (!Mutex.TryOpenExisting(MutexName, out Mutex mutex)) + { + mutex = new Mutex(false, MutexName); + + var loopbackEnabler = new LoopbackEnabler(); + loopbackEnabler.EnableForApp(Package.Current.DisplayName); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + string baseAddress = "http://localhost:9000/"; + + using (WebApp.Start(url: baseAddress)) + { + Application.Run(new SystemTrayApplicationContext()); + } + mutex.Close(); + } + } + } +} diff --git a/FluentTerminal.SystemTray/Properties/AssemblyInfo.cs b/FluentTerminal.SystemTray/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..dfea57e --- /dev/null +++ b/FluentTerminal.SystemTray/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die einer Assembly zugeordnet sind. +[assembly: AssemblyTitle("FluentTerminal.SystemTray")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FluentTerminal.SystemTray")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly +// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("9edde318-0003-4553-b6f9-3fe5473563fd")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +// übernehmen, indem Sie "*" eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/FluentTerminal.SystemTray/Properties/Resources.Designer.cs b/FluentTerminal.SystemTray/Properties/Resources.Designer.cs new file mode 100644 index 0000000..812df01 --- /dev/null +++ b/FluentTerminal.SystemTray/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace FluentTerminal.SystemTray.Properties { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FluentTerminal.SystemTray.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Icon ähnlich wie (Symbol). + /// + internal static System.Drawing.Icon Square44x44Logo_scale_100 { + get { + object obj = ResourceManager.GetObject("Square44x44Logo_scale_100", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + } +} diff --git a/FluentTerminal.SystemTray/Properties/Resources.resx b/FluentTerminal.SystemTray/Properties/Resources.resx new file mode 100644 index 0000000..2a81e71 --- /dev/null +++ b/FluentTerminal.SystemTray/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\Square44x44Logo.scale-100.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/FluentTerminal.SystemTray/Properties/Settings.Designer.cs b/FluentTerminal.SystemTray/Properties/Settings.Designer.cs new file mode 100644 index 0000000..e1b47aa --- /dev/null +++ b/FluentTerminal.SystemTray/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace FluentTerminal.SystemTray.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/FluentTerminal.SystemTray/Properties/Settings.settings b/FluentTerminal.SystemTray/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/FluentTerminal.SystemTray/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/FluentTerminal.SystemTray/Resources/Square44x44Logo.scale-100.ico b/FluentTerminal.SystemTray/Resources/Square44x44Logo.scale-100.ico new file mode 100644 index 0000000..f45747c Binary files /dev/null and b/FluentTerminal.SystemTray/Resources/Square44x44Logo.scale-100.ico differ diff --git a/FluentTerminal.SystemTray/Services/Terminal.cs b/FluentTerminal.SystemTray/Services/Terminal.cs new file mode 100644 index 0000000..f5d2208 --- /dev/null +++ b/FluentTerminal.SystemTray/Services/Terminal.cs @@ -0,0 +1,174 @@ +using Fleck; +using FluentTerminal.SystemTray.DataTransferObjects; +using System; +using System.IO; +using System.IO.Pipes; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using static winpty.WinPty; + +namespace FluentTerminal.SystemTray.Services +{ + public class Terminal : IDisposable + { + private IntPtr _handle; + private Stream _stdin; + private Stream _stdout; + private bool _disposedValue; + private ManualResetEventSlim _connectedEvent; + + private IWebSocketConnection _webSocket; + + public int Id { get; } + + public string WebSocketUrl { get; } + + public event EventHandler ConnectionClosed; + + public Terminal(TerminalOptions options) + { + var configHandle = IntPtr.Zero; + var spawnConfigHandle = IntPtr.Zero; + var errorHandle = IntPtr.Zero; + + try + { + configHandle = winpty_config_new(WINPTY_FLAG_COLOR_ESCAPES, out errorHandle); + winpty_config_set_initial_size(configHandle, options.Columns, options.Rows); + + _handle = winpty_open(configHandle, out errorHandle); + if (errorHandle != IntPtr.Zero) + { + throw new Exception(winpty_error_code(errorHandle).ToString()); + } + + string exe = @"C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe"; + string args = ""; + string cwd = @"C:\"; + spawnConfigHandle = winpty_spawn_config_new(WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, exe, args, cwd, null, out errorHandle); + if (errorHandle != IntPtr.Zero) + { + throw new Exception(winpty_error_code(errorHandle).ToString()); + } + + _stdin = CreatePipe(winpty_conin_name(_handle), PipeDirection.Out); + _stdout = CreatePipe(winpty_conout_name(_handle), PipeDirection.In); + + if (!winpty_spawn(_handle, spawnConfigHandle, out IntPtr process, out IntPtr thread, out int procError, out errorHandle)) + { + throw new Exception(winpty_error_code(errorHandle).ToString()); + } + } + finally + { + winpty_config_free(configHandle); + winpty_spawn_config_free(spawnConfigHandle); + winpty_error_free(errorHandle); + } + + + var port = Utilities.GetAvailablePort(49151); + + if (port == null) + { + throw new Exception("no port available"); + } + + Id = port.Value; + _connectedEvent = new ManualResetEventSlim(false); + WebSocketUrl = "ws://127.0.0.1:" + port; + var webSocketServer = new WebSocketServer(WebSocketUrl); + webSocketServer.Start(socket => + { + _webSocket = socket; + socket.OnOpen = () => + { + Console.WriteLine("open"); + _connectedEvent.Set(); + }; + socket.OnClose = () => + { + Console.WriteLine("closing"); + ConnectionClosed?.Invoke(this, EventArgs.Empty); + }; + socket.OnMessage = message => + { + var bytes = Encoding.ASCII.GetBytes(message); + _stdin.Write(bytes, 0, bytes.Length); + }; + }); + + ListenToStdOut(); + } + + private Stream CreatePipe(string pipeName, PipeDirection direction) + { + string serverName = "."; + if (pipeName.StartsWith("\\")) + { + int slash3 = pipeName.IndexOf('\\', 2); + if (slash3 != -1) + { + serverName = pipeName.Substring(2, slash3 - 2); + } + int slash4 = pipeName.IndexOf('\\', slash3 + 1); + if (slash4 != -1) + { + pipeName = pipeName.Substring(slash4 + 1); + } + } + + var pipe = new NamedPipeClientStream(serverName, pipeName, direction); + pipe.Connect(); + return pipe; + } + + private void ListenToStdOut() + { + Task.Run(async () => + { + _connectedEvent.Wait(); + var reader = new StreamReader(_stdout); + do + { + var offset = 0; + var buffer = new char[1024]; + var readChars = await reader.ReadAsync(buffer, offset, buffer.Length - offset); + if (readChars > 0) + { + await _webSocket.Send(new String(buffer)); + } + } + while (!reader.EndOfStream); + }); + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + _stdin?.Dispose(); + _stdout?.Dispose(); + } + + winpty_free(_handle); + + _disposedValue = true; + } + } + + ~Terminal() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + } +} diff --git a/FluentTerminal.SystemTray/Services/TerminalsManager.cs b/FluentTerminal.SystemTray/Services/TerminalsManager.cs new file mode 100644 index 0000000..9bbe030 --- /dev/null +++ b/FluentTerminal.SystemTray/Services/TerminalsManager.cs @@ -0,0 +1,32 @@ +using FluentTerminal.SystemTray.DataTransferObjects; +using System.Collections.Generic; + +namespace FluentTerminal.SystemTray.Services +{ + public class TerminalsManager + { + private Dictionary _terminals = new Dictionary(); + + public TerminalsManager() + { + + } + + public string CreateTerminal(TerminalOptions options) + { + var terminal = new Terminal(options); + terminal.ConnectionClosed += OnTerminalConnectionClosed; + _terminals.Add(terminal.Id, terminal); + return terminal.WebSocketUrl; + } + + private void OnTerminalConnectionClosed(object sender, System.EventArgs e) + { + if (sender is Terminal terminal) + { + _terminals.Remove(terminal.Id); + terminal.Dispose(); + } + } + } +} diff --git a/FluentTerminal.SystemTray/Startup.cs b/FluentTerminal.SystemTray/Startup.cs new file mode 100644 index 0000000..85c9cb0 --- /dev/null +++ b/FluentTerminal.SystemTray/Startup.cs @@ -0,0 +1,25 @@ +using FluentTerminal.SystemTray.Services; +using Owin; +using System.Web.Http; +using Unity; + +namespace FluentTerminal.SystemTray +{ + public class Startup + { + public void Configuration(IAppBuilder appBuilder) + { + HttpConfiguration config = new HttpConfiguration(); + config.MapHttpAttributeRoutes(); + + var container = new UnityContainer(); + container.RegisterType(); + + config.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container); + + //appBuilder.UseFileServer() + appBuilder.UseStaticFiles("/Client"); + appBuilder.UseWebApi(config); + } + } +} diff --git a/FluentTerminal.SystemTray/SystemTrayApplicationContext.cs b/FluentTerminal.SystemTray/SystemTrayApplicationContext.cs new file mode 100644 index 0000000..dc552be --- /dev/null +++ b/FluentTerminal.SystemTray/SystemTrayApplicationContext.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using Windows.ApplicationModel; +using Windows.ApplicationModel.AppService; +using Windows.ApplicationModel.Core; +using Windows.Foundation.Collections; + +namespace FluentTerminal.SystemTray +{ + public class SystemTrayApplicationContext : ApplicationContext + { + private AppServiceConnection connection = null; + private NotifyIcon notifyIcon = null; + + public SystemTrayApplicationContext() + + { + var openMenuItem = new MenuItem("Open App", new EventHandler(OpenApp)); + var exitMenuItem = new MenuItem("Exit", new EventHandler(Exit)); + + openMenuItem.DefaultItem = true; + + notifyIcon = new NotifyIcon(); + notifyIcon.DoubleClick += OpenApp; + notifyIcon.Text = "Fluent Terminal"; + notifyIcon.Icon = Properties.Resources.Square44x44Logo_scale_100; + notifyIcon.ContextMenu = new ContextMenu(new MenuItem[] { openMenuItem, exitMenuItem }); + notifyIcon.Visible = true; + } + + private async void OpenApp(object sender, EventArgs e) + { + IEnumerable appListEntries = await Package.Current.GetAppListEntriesAsync(); + await appListEntries.First().LaunchAsync(); + } + + private async void Exit(object sender, EventArgs e) + + { + var message = new ValueSet + { + { "exit", string.Empty } + }; + await SendMessage(message); + Application.Exit(); + } + + private async Task SendMessage(ValueSet message) + + { + if (connection == null) + { + connection = new AppServiceConnection + { + PackageFamilyName = Package.Current.Id.FamilyName, + AppServiceName = "FluentTerminalAppService" + }; + connection.ServiceClosed += Connection_ServiceClosed; + AppServiceConnectionStatus connectionStatus = await connection.OpenAsync(); + + if (connectionStatus != AppServiceConnectionStatus.Success) + { + MessageBox.Show("Status: " + connectionStatus.ToString()); + return; + } + } + await connection.SendMessageAsync(message); + } + + private void Connection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args) + { + connection.ServiceClosed -= Connection_ServiceClosed; + connection = null; + } + } +} \ No newline at end of file diff --git a/FluentTerminal.SystemTray/Utilities.cs b/FluentTerminal.SystemTray/Utilities.cs new file mode 100644 index 0000000..77cd728 --- /dev/null +++ b/FluentTerminal.SystemTray/Utilities.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.NetworkInformation; + +namespace FluentTerminal.SystemTray +{ + public static class Utilities + { + public static int? GetAvailablePort(int startingPort) + { + var usedPorts = new List(); + + var properties = IPGlobalProperties.GetIPGlobalProperties(); + + var connections = properties.GetActiveTcpConnections(); + usedPorts.AddRange(connections.Where(c => c.LocalEndPoint.Port >= startingPort).Select(c => c.LocalEndPoint.Port)); + + var endPoints = properties.GetActiveTcpListeners(); + usedPorts.AddRange(endPoints.Where(e => e.Port >= startingPort).Select(e => e.Port)); + + endPoints = properties.GetActiveUdpListeners(); + usedPorts.AddRange(endPoints.Where(e => e.Port >= startingPort).Select(e => e.Port)); + + usedPorts.Sort(); + + for (var i = startingPort; i < UInt16.MaxValue; i++) + { + if (!usedPorts.Contains(i)) + { + return i; + } + } + return null; + } + } +} diff --git a/FluentTerminal.SystemTray/app.manifest b/FluentTerminal.SystemTray/app.manifest new file mode 100644 index 0000000..a5e87dc --- /dev/null +++ b/FluentTerminal.SystemTray/app.manifest @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FluentTerminal.sln b/FluentTerminal.sln new file mode 100644 index 0000000..9fc512d --- /dev/null +++ b/FluentTerminal.sln @@ -0,0 +1,68 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2020 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentTerminal.App", "FluentTerminal.App\FluentTerminal.App.csproj", "{41020100-3414-4E0A-9A8E-92D3C4179DF8}" + ProjectSection(ProjectDependencies) = postProject + {9EDDE318-0003-4553-B6F9-3FE5473563FD} = {9EDDE318-0003-4553-B6F9-3FE5473563FD} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentTerminal.SystemTray", "FluentTerminal.SystemTray\FluentTerminal.SystemTray.csproj", "{9EDDE318-0003-4553-B6F9-3FE5473563FD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Debug|Any CPU.ActiveCfg = Debug|x86 + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Debug|ARM.ActiveCfg = Debug|ARM + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Debug|ARM.Build.0 = Debug|ARM + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Debug|ARM.Deploy.0 = Debug|ARM + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Debug|x64.ActiveCfg = Debug|x64 + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Debug|x64.Build.0 = Debug|x64 + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Debug|x64.Deploy.0 = Debug|x64 + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Debug|x86.ActiveCfg = Debug|x86 + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Debug|x86.Build.0 = Debug|x86 + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Debug|x86.Deploy.0 = Debug|x86 + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Release|Any CPU.ActiveCfg = Release|x86 + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Release|ARM.ActiveCfg = Release|ARM + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Release|ARM.Build.0 = Release|ARM + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Release|ARM.Deploy.0 = Release|ARM + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Release|x64.ActiveCfg = Release|x64 + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Release|x64.Build.0 = Release|x64 + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Release|x64.Deploy.0 = Release|x64 + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Release|x86.ActiveCfg = Release|x86 + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Release|x86.Build.0 = Release|x86 + {41020100-3414-4E0A-9A8E-92D3C4179DF8}.Release|x86.Deploy.0 = Release|x86 + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Debug|ARM.ActiveCfg = Debug|Any CPU + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Debug|ARM.Build.0 = Debug|Any CPU + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Debug|x64.ActiveCfg = Debug|x64 + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Debug|x64.Build.0 = Debug|x64 + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Debug|x86.ActiveCfg = Debug|x86 + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Debug|x86.Build.0 = Debug|x86 + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Release|Any CPU.Build.0 = Release|Any CPU + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Release|ARM.ActiveCfg = Release|Any CPU + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Release|ARM.Build.0 = Release|Any CPU + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Release|x64.ActiveCfg = Release|x64 + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Release|x64.Build.0 = Release|x64 + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Release|x86.ActiveCfg = Release|x86 + {9EDDE318-0003-4553-B6F9-3FE5473563FD}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {094EE77F-2C87-4E36-BBFF-C093D31D4DA7} + EndGlobalSection +EndGlobal diff --git a/xterm.js/.dockerignore b/xterm.js/.dockerignore new file mode 100644 index 0000000..c837dec --- /dev/null +++ b/xterm.js/.dockerignore @@ -0,0 +1,16 @@ +node_modules/ +*.swp +.lock-wscript +lib/ +Makefile.gyp +*.Makefile +*.target.gyp.mk +*.node +example/*.log +docs/ +npm-debug.log +/.idea/ +.env +build/ +.vscode/ +.git/ diff --git a/xterm.js/.editorconfig b/xterm.js/.editorconfig new file mode 100644 index 0000000..26230e9 --- /dev/null +++ b/xterm.js/.editorconfig @@ -0,0 +1,17 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true +end_of_line = lf + +[*.{j,t}s] +max_line_length = 100 + +[*.css] +indent_size = 4 + +[*.md] +trim_trailing_whitespace = false diff --git a/xterm.js/.gitattributes b/xterm.js/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/xterm.js/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/xterm.js/.github/ISSUE_TEMPLATE.md b/xterm.js/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..3593535 --- /dev/null +++ b/xterm.js/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,11 @@ + + +## Details +- Browser and browser version: +- OS version: +- xterm.js version: + +### Steps to reproduce + +1. +2. diff --git a/xterm.js/.gitignore b/xterm.js/.gitignore new file mode 100644 index 0000000..bf0c3d8 --- /dev/null +++ b/xterm.js/.gitignore @@ -0,0 +1,28 @@ +node_modules/ +*.swp +.lock-wscript +lib/ +Makefile.gyp +*.Makefile +*.target.gyp.mk +*.node +example/*.log +docs/ +npm-debug.log +/.idea/ +.env +build/ +.vscode/ +.DS_Store +fixtures/typings-test/*.js + +# Directories needed for code coverage +/coverage/ + +# Keep legacy files out of the repo, this can be removed when we merge v3 into master +dist/ +src/utils/TestUtils.ts +src/xterm.js + +# Keep the demo builds out of Git +demo/dist/ diff --git a/xterm.js/.gitmodules b/xterm.js/.gitmodules new file mode 100644 index 0000000..e69de29 diff --git a/xterm.js/.mailmap b/xterm.js/.mailmap new file mode 100644 index 0000000..a8de62a --- /dev/null +++ b/xterm.js/.mailmap @@ -0,0 +1,7 @@ +Antonis Kalipetis +Antonis Kalipetis +Daniel Imms +Paris Kasidiaris +Paris Kasidiaris +Thanasis Daglis +Thanasis Daglis diff --git a/xterm.js/.npmignore b/xterm.js/.npmignore new file mode 100644 index 0000000..63069bd --- /dev/null +++ b/xterm.js/.npmignore @@ -0,0 +1,16 @@ +node_modules/ +*.swp +.lock-wscript +lib/*.test.js +lib/*.test.js.map +lib/test/ +Makefile.gyp +*.Makefile +*.target.gyp.mk +*.node +example/*.log +docs/ +npm-debug.log +/.idea/ +.env +build/ diff --git a/xterm.js/.travis.yml b/xterm.js/.travis.yml new file mode 100644 index 0000000..1878c3a --- /dev/null +++ b/xterm.js/.travis.yml @@ -0,0 +1,20 @@ +language: node_js +os: + - linux + - osx +node_js: + - 6 +before_install: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test ; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq update ; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -qq install g++-4.8 ; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export CXX=g++-4.8 ; fi + - npm install -g npm@5.1.0 +env: + matrix: + - NPM_COMMAND=lint + - NPM_COMMAND=test +notifications: + email: false +script: npm run $NPM_COMMAND +after_success: npm run coveralls diff --git a/xterm.js/AUTHORS b/xterm.js/AUTHORS new file mode 100644 index 0000000..1bd4c87 --- /dev/null +++ b/xterm.js/AUTHORS @@ -0,0 +1,92 @@ +List of xterm.js contributors. Updated before every release. + +Aleksandr Andrienko +Aleksandr Andriienko +Alessandro Nadalin +Alexander Olsson +Alexey Kontsevoy +Anish Athalye +Anthony Lapenna +Antonis Kalipetis +Anton Skshidlevsky +Anton Yurovskykh +Artem Arbatskiy +Austin Robertson +ayapi +Ben Hall +Benjamin Fischer +Bill Church +Bob Reid +bottleofwater +Brian Mock +Bruno Ribeito +Carson Anderson +CHaBou +Christian Budde Christensen +Christof Marti +Christopher Jeffrey +coderaiser +Dan Brown +Daniel Griffen +Daniel Imms +Daniel Risacher +Dan Kaplun +Darin Morrison +dcylabs +Dominik Csapak +Edgar Andrés Margffoy Tuay +Elliot Saba +Exile +Felipe Gasper +ficristo +Gary Ritchie +hiro-su +Ian Lewis +imoses +InDieTasten +irokas +Jakob Gillich +Jean Bruenn +Jeremy Danyow +Joao Moreno +Joao Moreno +Johannes Zellner +Jon Masters +Jörg Breitbart +Justin Mecham +Kirill Merkushev +Luca +Lucian Buzzo +Lukas Drgon +Maël Nison +Marc Dumais +Martin Chloride +Martin Koppehel +Martin Wang +Matt Bierner +Michael Irwin +Mikko Karvonen +mofux +Nicolas Ramz +npezza93 +Oleksandr Andriienko +Paris Kasidiaris +Paris Kasidiaris +Peter Baumgarten +Rick Baker +runarberg +Samuel Williams +Saswat Das +Saul Costa +Shuanglei Tao +Steven Silvester +stuicey +t-amqi +Thanasis Daglis +thomas +Thomas Zilz +Tine Jozelj +Tyler Jewell +Vincent Woo +yutaka +YuviPanda diff --git a/xterm.js/CONTRIBUTING.md b/xterm.js/CONTRIBUTING.md new file mode 100644 index 0000000..8b33d18 --- /dev/null +++ b/xterm.js/CONTRIBUTING.md @@ -0,0 +1,52 @@ +# How to contribute to xterm.js + +- [Opening issues for bug reports or feature requests](#opening-issues) +- [Contributing code](#contributing-code) + +## Opening issues + +The preferred way to report bugs or request features is to use +[GitHub issues](http://github.com/sourcelair/xterm.js/issues). Before +opening an issue, read these pointers. + +### Opening issues effectively + +- Include information about **the browser in which the problem occurred**. Even + if you tested several browsers, and the problem occurred in all of them, + mention this fact in the bug report. Also include browser version numbers and + the operating system that you're on. + +- Mention which release of xterm.js you're using. Preferably, try also with + the current HEAD of the master branch, to ensure the problem has not already been + fixed. + +- Mention precisely what went wrong. What did you expect to happen? What happened instead? Describe the + exact steps a maintainer has to take to make the problem occur. + +- If the problem can not be reproduced in the [demo of xterm.js](README.md#demo), please provide an HTML document that demonstrates the problem. + +- Be polite. Issues with an indignant or belligerent tone tend to be moved to the + bottom of the pile. + +## Contributing code + +- Make sure you have a [GitHub account](https://github.com/join) +- Fork [xterm.js](https://github.com/sourcelair/xterm.js/) + ([how to fork a repo](https://help.github.com/articles/fork-a-repo)) +- Make your changes +- If your changes are easy to test or likely to regress, add tests. Tests go into `test`, directory. +- Follow the general code style of the rest of the project (see below). +- Submit a pull request +([how to create a pull request](https://help.github.com/articles/fork-a-repo)). + Don't put more than one feature/fix in a single pull request. + +By contributing code to xterm.js you + + - agree to license the contributed code under xterm.js' [MIT + license](LICENSE). + + - confirm that you have the right to contribute and license the code + in question. (Either you hold all rights on the code, or the rights + holder has explicitly granted the right to use it like this, + through a compatible open source license or through a direct + agreement with you.) diff --git a/xterm.js/Dockerfile b/xterm.js/Dockerfile new file mode 100644 index 0000000..22556f4 --- /dev/null +++ b/xterm.js/Dockerfile @@ -0,0 +1,19 @@ +FROM node:6 +MAINTAINER Paris Kasidiaris + +# Set the working directory +WORKDIR /usr/src/app + +# Set an entrypoint, to automatically install node modules +ENTRYPOINT ["/bin/bash", "-c", "if [[ ! -d node_modules ]]; then npm install; fi; exec \"${@:0}\";"] +CMD ["npm", "run", "start"] + +# First, install dependencies to improve layer caching +COPY package.json /usr/src/app/ +RUN npm install + +# Add the code +COPY . /usr/src/app + +# Run the tests and build, to make sure everything is working nicely +RUN npm run build && npm run test diff --git a/xterm.js/LICENSE b/xterm.js/LICENSE new file mode 100644 index 0000000..648a90e --- /dev/null +++ b/xterm.js/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2014-2016, SourceLair Private Company (https://www.sourcelair.com) +Copyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/xterm.js/Procfile b/xterm.js/Procfile new file mode 100644 index 0000000..063b78f --- /dev/null +++ b/xterm.js/Procfile @@ -0,0 +1 @@ +web: npm start diff --git a/xterm.js/README.md b/xterm.js/README.md new file mode 100644 index 0000000..1719efb --- /dev/null +++ b/xterm.js/README.md @@ -0,0 +1,170 @@ +# [![xterm.js logo](logo-full.png)](https://xtermjs.org) + +[![xterm.js build status](https://api.travis-ci.org/xtermjs/xterm.js.svg)](https://travis-ci.org/xtermjs/xterm.js) [![Coverage Status](https://coveralls.io/repos/github/sourcelair/xterm.js/badge.svg)](https://coveralls.io/github/sourcelair/xterm.js) [![Gitter](https://badges.gitter.im/sourcelair/xterm.js.svg)](https://gitter.im/sourcelair/xterm.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/xterm/badge?style=rounded)](https://www.jsdelivr.com/package/npm/xterm) + +Xterm.js is a terminal front-end component written in JavaScript that works in the browser. + +It enables applications to provide fully featured terminals to their users and create great development experiences. + +## Features +- **Text-based application support**: Use xterm.js to work with applications like `bash`, `git` etc. +- **Curses-based application support**: Use xterm.js to work with applications like `vim`, `tmux` etc. +- **Mouse events support**: Xterm.js captures mouse events like click and scroll and passes them to the terminal's back-end controlling process +- **CJK (Chinese, Japanese, Korean) character support**: Xterm.js renders CJK characters seamlessly +- **IME support**: Insert international (including CJK) characters using IME input with your keyboard +- **Self-contained library**: Xterm.js works on its own. It does not require any external libraries like jQuery or React to work +- **Modular, event-based API**: Lets you build addons and themes with ease + +## What xterm.js is not +- Xterm.js is not a terminal application that you can download and use on your computer +- Xterm.js is not `bash`. Xterm.js can be connected to processes like `bash` and let you interact with them (provide input, receive output) + +## Getting Started + +First you need to install the module, we ship exclusively through [npm](https://www.npmjs.com/) so you need that installed and then add xterm.js as a dependency by running: + +``` +npm install +``` + +To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to the head of your html page. Then create a `
` onto which xterm can attach itself. + +```html + + + + + + + +
+ + + +``` + +Finally instantiate the `Terminal` object and then call the `open` function with the DOM object of the `div`. + +### Importing + +The proposed way to load xterm.js is via the ES6 module syntax. + +```javascript +import { Terminal } from 'xterm'; +``` + +*Note: There are currently no typings for addons so you will need to upcast if using TypeScript, eg. `(xterm).fit()`.* + +### Addons + +Addons are JavaScript modules that extend the `Terminal` prototype with new methods and attributes to provide additional functionality. There are a handful available in the main repository in the `src/addons` directory and you can even write your own, by using xterm.js' public API. + +To use an addon, just import the JavaScript module and pass it to `Terminal`'s `applyAddon` method: + +```javascript +import { Terminal } from xterm; +import * as fit from 'xterm/lib/addons/fit/fit'; + + +Terminal.applyAddon(fit); + +var xterm = new Terminal(); // Instantiate the terminal +xterm.fit(); // Use the `fit` method, provided by the `fit` addon +``` + +## Browser Support + +Since xterm.js is typically implemented as a developer tool, only modern browsers are supported officially. Here is a list of the versions we aim to support: + +- Chrome latest +- Edge latest +- Firefox latest +- Safari latest +- IE11 + +Xterm.js works seamlessly in Electron apps and may even work on earlier versions of the browsers but these are the browsers we strive to keep working. + +## Real-world uses +Xterm.js is used in several world-class applications to provide great terminal experiences. + +- [**SourceLair**](https://www.sourcelair.com/): In-browser IDE that provides its users with fully-featured Linux terminals based on xterm.js +- [**Microsoft Visual Studio Code**](http://code.visualstudio.com/): Modern, versatile and powerful open source code editor that provides an integrated terminal based on xterm.js +- [**ttyd**](https://github.com/tsl0922/ttyd): A command-line tool for sharing terminal over the web, with fully-featured terminal emulation based on xterm.js +- [**Katacoda**](https://www.katacoda.com/): Katacoda is an Interactive Learning Platform for software developers, covering the latest Cloud Native technologies. +- [**Eclipse Che**](http://www.eclipse.org/che): Developer workspace server, cloud IDE, and Eclipse next-generation IDE. +- [**Codenvy**](http://www.codenvy.com): Cloud workspaces for development teams. +- [**CoderPad**](https://coderpad.io): Online interviewing platform for programmers. Run code in many programming languages, with results displayed by `xterm.js`. +- [**WebSSH2**](https://github.com/billchurch/WebSSH2): A web based SSH2 client using `xterm.js`, socket.io, and ssh2. +- [**Spyder Terminal**](https://github.com/spyder-ide/spyder-terminal): A full fledged system terminal embedded on Spyder IDE. +- [**Cloud Commander**](https://cloudcmd.io "Cloud Commander"): Orthodox web file manager with console and editor. +- [**Codevolve**](https://www.codevolve.com "Codevolve"): Online platform for interactive coding and web development courses. Live container-backed terminal uses `xterm.js`. +- [**RStudio**](https://www.rstudio.com/products/RStudio "RStudio"): RStudio is an integrated development environment (IDE) for R. +- [**Terminal for Atom**](https://github.com/jsmecham/atom-terminal-tab): A simple terminal for the Atom text editor. +- [**Eclipse Orion**](https://orionhub.org): A modern, open source software development environment that runs in the cloud. Code, deploy and run in the cloud. +- [**Gravitational Teleport**](https://github.com/gravitational/teleport): Gravitational Teleport is a modern SSH server for remotely accessing clusters of Linux servers via SSH or HTTPS. +- [**Hexlet**](https://en.hexlet.io): Practical programming courses (JavaScript, PHP, Unix, databases, functional programming). A steady path from the first line of code to the first job. +- [**Selenoid UI**](https://github.com/aerokube/selenoid-ui): Simple UI for the scallable golang implementation of Selenium Hub named Selenoid. We use XTerm for streaming logs over websockets from docker containers. +- [**Portainer**](https://portainer.io): Simple management UI for Docker. +- [**SSHy**](https://github.com/stuicey/SSHy): HTML5 Based SSHv2 Web Client with E2E encryption utilising `xterm.js`, SJCL & websockets. +- [**JupyterLab**](https://github.com/jupyterlab/jupyterlab): An extensible +computational environment for Jupyter, supporting interactive data science and scientific computing across all programming languages. +- [**Theia**](https://github.com/theia-ide/theia): Theia is a cloud & desktop IDE framework implemented in TypeScript. +- [**Opshell**](https://github.com/ricktbaker/opshell) Ops Helper tool to make life easier working with AWS instances across multiple organizations. +- [**Proxmox VE**](https://www.proxmox.com/en/proxmox-ve): Proxmox VE is a complete open-source platform for enterprise virtualization. It uses xterm.js for container terminals and the host shell. +- [**Script Runner**](https://github.com/ioquatix/script-runner): Run scripts (or a shell) in Atom. +- [**Whack Whack Terminal**](https://github.com/Microsoft/WhackWhackTerminal): Terminal emulator for Visual Studio 2017. +- [**VTerm**](https://github.com/vterm/vterm): Extensible terminal emulator based on Electron and React. +- [**electerm**](http://electerm.html5beta.com): electerm is a terminal/ssh/sftp client(mac, win, linux) based on electron/node-pty/xterm. +- [**Kubebox**](https://github.com/astefanutti/kubebox): Terminal console for Kubernetes clusters. + +Do you use xterm.js in your application as well? Please [open a Pull Request](https://github.com/sourcelair/xterm.js/pulls) to include it here. We would love to have it in our list. + +## Demo + +### Linux or macOS + +First, be sure that a C++ compiler such as GCC-C++ or Clang is installed, then run these commands: + +``` +npm install +npm start +``` + +Then open http://0.0.0.0:3000 in a web browser. + +### Windows + +First, ensure [node-gyp](https://github.com/nodejs/node-gyp) is installed and configured correctly, then run these commands. + +``` +npm install +npm start +``` + +Then open http://127.0.0.1:3000 in a web browser. + +*Note: Do not use ConEmu, as it seems to break the demo for some reason.* + +## Releases + +Xterm.js follows a monthly release cycle roughly. + +The existing releases are available at this GitHub repo's [Releases](https://github.com/sourcelair/xterm.js/releases), while the roadmap is available as [Milestones](https://github.com/sourcelair/xterm.js/milestones). + +## Development and Contribution + +Xterm.js is maintained by [SourceLair](https://www.sourcelair.com/) and a few external contributors, but we would love to receive contributions from everyone! + +To contribute either code, documentation or issues to xterm.js please read the [Contributing document](CONTRIBUTING.md) beforehand. The development of xterm.js does not require any special tool. All you need is an editor that supports JavaScript/TypeScript and a browser. You will need Node.js installed locally to get all the features working in the demo. + +## License Agreement + +If you contribute code to this project, you are implicitly allowing your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work. + +Copyright (c) 2014-2017, SourceLair, Private Company ([www.sourcelair.com](https://www.sourcelair.com/home)) (MIT License) + +Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) diff --git a/xterm.js/demo/app.js b/xterm.js/demo/app.js new file mode 100644 index 0000000..7604e9c --- /dev/null +++ b/xterm.js/demo/app.js @@ -0,0 +1,88 @@ +var express = require('express'); +var app = express(); +var expressWs = require('express-ws')(app); +var os = require('os'); +var pty = require('node-pty'); + +var terminals = {}, + logs = {}; + +app.use('/build', express.static(__dirname + '/../build')); + +app.get('/', function(req, res){ + res.sendFile(__dirname + '/index.html'); +}); + +app.get('/style.css', function(req, res){ + res.sendFile(__dirname + '/style.css'); +}); + +app.get('/dist/bundle.js', function(req, res){ + res.sendFile(__dirname + '/dist/bundle.js'); +}); + +app.get('/dist/bundle.js.map', function(req, res){ + res.sendFile(__dirname + '/dist/bundle.js.map'); +}); + +app.post('/terminals', function (req, res) { + var cols = parseInt(req.query.cols), + rows = parseInt(req.query.rows), + term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], { + name: 'xterm-color', + cols: cols || 80, + rows: rows || 24, + cwd: process.env.PWD, + env: process.env + }); + + console.log('Created terminal with PID: ' + term.pid); + terminals[term.pid] = term; + logs[term.pid] = ''; + term.on('data', function(data) { + logs[term.pid] += data; + }); + res.send(term.pid.toString()); + res.end(); +}); + +app.post('/terminals/:pid/size', function (req, res) { + var pid = parseInt(req.params.pid), + cols = parseInt(req.query.cols), + rows = parseInt(req.query.rows), + term = terminals[pid]; + + term.resize(cols, rows); + console.log('Resized terminal ' + pid + ' to ' + cols + ' cols and ' + rows + ' rows.'); + res.end(); +}); + +app.ws('/terminals/:pid', function (ws, req) { + var term = terminals[parseInt(req.params.pid)]; + console.log('Connected to terminal ' + term.pid); + ws.send(logs[term.pid]); + + term.on('data', function(data) { + try { + ws.send(data); + } catch (ex) { + // The WebSocket is not open, ignore + } + }); + ws.on('message', function(msg) { + term.write(msg); + }); + ws.on('close', function () { + term.kill(); + console.log('Closed terminal ' + term.pid); + // Clean things up + delete terminals[term.pid]; + delete logs[term.pid]; + }); +}); + +var port = process.env.PORT || 3000, + host = os.platform() === 'win32' ? '127.0.0.1' : '0.0.0.0'; + +console.log('App listening to http://' + host + ':' + port); +app.listen(port, host); diff --git a/xterm.js/demo/index.html b/xterm.js/demo/index.html new file mode 100644 index 0000000..93399f9 --- /dev/null +++ b/xterm.js/demo/index.html @@ -0,0 +1,70 @@ + + + + xterm.js demo + + + + + + + +

xterm.js: xterm, in the browser

+
+
+

Actions

+

+ + +

+
+
+

Options

+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+
+

Size

+
+
+ + +
+
+ + +
+
+
+
+

Attention: The demo is a barebones implementation and is designed for xterm.js evaluation purposes only. Exposing the demo to the public as is would introduce security risks for the host.

+ + + diff --git a/xterm.js/demo/main.js b/xterm.js/demo/main.js new file mode 100644 index 0000000..95b15a0 --- /dev/null +++ b/xterm.js/demo/main.js @@ -0,0 +1,179 @@ +import * as Terminal from '../build/xterm'; +import * as attach from '../build/addons/attach/attach'; +import * as fit from '../build/addons/fit/fit'; +import * as fullscreen from '../build/addons/fullscreen/fullscreen'; +import * as search from '../build/addons/search/search'; +import * as winptyCompat from '../build/addons/winptyCompat/winptyCompat'; + + +Terminal.applyAddon(attach); +Terminal.applyAddon(fit); +Terminal.applyAddon(fullscreen); +Terminal.applyAddon(search); +Terminal.applyAddon(winptyCompat); + + +var term, + protocol, + socketURL, + socket, + pid; + +var terminalContainer = document.getElementById('terminal-container'), + actionElements = { + findNext: document.querySelector('#find-next'), + findPrevious: document.querySelector('#find-previous') + }, + optionElements = { + cursorBlink: document.querySelector('#option-cursor-blink'), + cursorStyle: document.querySelector('#option-cursor-style'), + scrollback: document.querySelector('#option-scrollback'), + tabstopwidth: document.querySelector('#option-tabstopwidth'), + bellStyle: document.querySelector('#option-bell-style') + }, + colsElement = document.getElementById('cols'), + rowsElement = document.getElementById('rows'); + +function setTerminalSize() { + var cols = parseInt(colsElement.value, 10); + var rows = parseInt(rowsElement.value, 10); + var viewportElement = document.querySelector('.xterm-viewport'); + var scrollBarWidth = viewportElement.offsetWidth - viewportElement.clientWidth; + var width = (cols * term.renderer.dimensions.actualCellWidth + 20 /*room for scrollbar*/).toString() + 'px'; + var height = (rows * term.renderer.dimensions.actualCellHeight).toString() + 'px'; + + terminalContainer.style.width = width; + terminalContainer.style.height = height; + term.resize(cols, rows); +} + +colsElement.addEventListener('change', setTerminalSize); +rowsElement.addEventListener('change', setTerminalSize); + +actionElements.findNext.addEventListener('keypress', function (e) { + if (e.key === "Enter") { + e.preventDefault(); + term.findNext(actionElements.findNext.value); + } +}); +actionElements.findPrevious.addEventListener('keypress', function (e) { + if (e.key === "Enter") { + e.preventDefault(); + term.findPrevious(actionElements.findPrevious.value); + } +}); + +optionElements.cursorBlink.addEventListener('change', function () { + term.setOption('cursorBlink', optionElements.cursorBlink.checked); +}); +optionElements.cursorStyle.addEventListener('change', function () { + term.setOption('cursorStyle', optionElements.cursorStyle.value); +}); +optionElements.bellStyle.addEventListener('change', function () { + term.setOption('bellStyle', optionElements.bellStyle.value); +}); +optionElements.scrollback.addEventListener('change', function () { + term.setOption('scrollback', parseInt(optionElements.scrollback.value, 10)); +}); +optionElements.tabstopwidth.addEventListener('change', function () { + term.setOption('tabStopWidth', parseInt(optionElements.tabstopwidth.value, 10)); +}); + +createTerminal(); + +function createTerminal() { + // Clean terminal + while (terminalContainer.children.length) { + terminalContainer.removeChild(terminalContainer.children[0]); + } + term = new Terminal({ + cursorBlink: optionElements.cursorBlink.checked, + scrollback: parseInt(optionElements.scrollback.value, 10), + tabStopWidth: parseInt(optionElements.tabstopwidth.value, 10) + }); + window.term = term; // Expose `term` to window for debugging purposes + term.on('resize', function (size) { + if (!pid) { + return; + } + var cols = size.cols, + rows = size.rows, + url = '/terminals/' + pid + '/size?cols=' + cols + '&rows=' + rows; + + fetch(url, {method: 'POST'}); + }); + protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://'; + socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/terminals/'; + + term.open(terminalContainer); + term.winptyCompatInit(); + term.fit(); + term.focus(); + + // fit is called within a setTimeout, cols and rows need this. + setTimeout(function () { + colsElement.value = term.cols; + rowsElement.value = term.rows; + + // Set terminal size again to set the specific dimensions on the demo + setTerminalSize(); + + fetch('/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then(function (res) { + + res.text().then(function (processId) { + pid = processId; + socketURL += processId; + socket = new WebSocket(socketURL); + socket.onopen = runRealTerminal; + socket.onclose = runFakeTerminal; + socket.onerror = runFakeTerminal; + }); + }); + }, 0); +} + +function runRealTerminal() { + term.attach(socket); + term._initialized = true; +} + +function runFakeTerminal() { + if (term._initialized) { + return; + } + + term._initialized = true; + + var shellprompt = '$ '; + + term.prompt = function () { + term.write('\r\n' + shellprompt); + }; + + term.writeln('Welcome to xterm.js'); + term.writeln('This is a local terminal emulation, without a real terminal in the back-end.'); + term.writeln('Type some keys and commands to play around.'); + term.writeln(''); + term.prompt(); + + term.on('key', function (key, ev) { + var printable = ( + !ev.altKey && !ev.altGraphKey && !ev.ctrlKey && !ev.metaKey + ); + + if (ev.keyCode == 13) { + term.prompt(); + } else if (ev.keyCode == 8) { + // Do not delete the prompt + if (term.x > 2) { + term.write('\b \b'); + } + } else if (printable) { + term.write(key); + } + }); + + term.on('paste', function (data, ev) { + term.write(data); + }); +} diff --git a/xterm.js/demo/style.css b/xterm.js/demo/style.css new file mode 100644 index 0000000..1ab5f61 --- /dev/null +++ b/xterm.js/demo/style.css @@ -0,0 +1,16 @@ +body { + font-family: helvetica, sans-serif, arial; + font-size: 1em; + color: #111; +} + +h1 { + text-align: center; +} + +#terminal-container { + width: 800px; + height: 450px; + margin: 0 auto; + padding: 2px; +} diff --git a/xterm.js/docker-compose.yml b/xterm.js/docker-compose.yml new file mode 100644 index 0000000..03e88fb --- /dev/null +++ b/xterm.js/docker-compose.yml @@ -0,0 +1,9 @@ +version: "3" + +services: + web: + build: . + volumes: + - ./:/usr/src/app + ports: + - ${XTERMJS_PORT:3000}:3000 diff --git a/xterm.js/fixtures/escape_sequence_files/NOTES b/xterm.js/fixtures/escape_sequence_files/NOTES new file mode 100644 index 0000000..bcadcb4 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/NOTES @@ -0,0 +1,21 @@ +All tests are made for 80x25 terminal. Make sure to run tests with 80x25. + +Create .text files from xterm (expected output) +- open xterm +- resize xterm to 80x25 +- run `python run_tests.py` +- copy & paste whole window output into editor +- add 26th empty line (due to line handling in toString) - not a bug, a feature ;) +- advance to next test with ^D + + +Known problems +############## + + +t0031-HBP: + - no documentation at all about CSIj found - skipping + +t0050-ICH: + - bug in xterm? (cant ICH last real char, always sticks to last col) + - text used from https://github.com/MarkLodato/vt100-parser/blob/master/test/t0050-ICH.text diff --git a/xterm.js/fixtures/escape_sequence_files/t0001-all_printable.in b/xterm.js/fixtures/escape_sequence_files/t0001-all_printable.in new file mode 100644 index 0000000..2f36543 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0001-all_printable.in @@ -0,0 +1,6 @@ + !"#$%&'()*+,-./ +0123456789:;<=>? +@ABCDEFGHIJKLMNO +PQRSTUVWXYZ[\]^_ +`abcdefghijklmno +pqrstuvwxyz{|}~ diff --git a/xterm.js/fixtures/escape_sequence_files/t0001-all_printable.text b/xterm.js/fixtures/escape_sequence_files/t0001-all_printable.text new file mode 100644 index 0000000..421f5a7 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0001-all_printable.text @@ -0,0 +1,25 @@ + !"#$%&'()*+,-./ +0123456789:;<=>? +@ABCDEFGHIJKLMNO +PQRSTUVWXYZ[\]^_ +`abcdefghijklmno +pqrstuvwxyz{|}~ + + + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0002-history.in b/xterm.js/fixtures/escape_sequence_files/t0002-history.in new file mode 100644 index 0000000..3bc7fbc --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0002-history.in @@ -0,0 +1,95 @@ + +! +" +# +$ +% +& +' +( +) +* ++ +, +- +. +/ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +: +; +< += +> +? +@ +A +B +C +D +E +F +G +H +I +J +K +L +M +N +O +P +Q +R +S +T +U +V +W +X +Y +Z +[ +\ +] +^ +_ +` +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +{ +| +} +~ diff --git a/xterm.js/fixtures/escape_sequence_files/t0002-history.text b/xterm.js/fixtures/escape_sequence_files/t0002-history.text new file mode 100644 index 0000000..39bdf52 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0002-history.text @@ -0,0 +1,25 @@ +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +{ +| +} +~ + diff --git a/xterm.js/fixtures/escape_sequence_files/t0002j-simple_string.in b/xterm.js/fixtures/escape_sequence_files/t0002j-simple_string.in new file mode 100644 index 0000000..a679175 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0002j-simple_string.in @@ -0,0 +1 @@ +abcdefghijklmnopqrstuvwxyz0123456789 \ No newline at end of file diff --git a/xterm.js/fixtures/escape_sequence_files/t0002j-simple_string.text b/xterm.js/fixtures/escape_sequence_files/t0002j-simple_string.text new file mode 100644 index 0000000..097318d --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0002j-simple_string.text @@ -0,0 +1,25 @@ +abcdefghijklmnopqrstuvwxyz0123456789 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0003-line_wrap.in b/xterm.js/fixtures/escape_sequence_files/t0003-line_wrap.in new file mode 100644 index 0000000..d110db8 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0003-line_wrap.in @@ -0,0 +1,83 @@ +a +ab +abc +abcd +abcde +abcdef +abcdefg +abcdefgh +abcdefghi +abcdefghij +abcdefghijk +abcdefghijkl +abcdefghijklm +abcdefghijklmn +abcdefghijklmno +abcdefghijklmnop +abcdefghijklmnopq +abcdefghijklmnopqr +abcdefghijklmnopqrs +abcdefghijklmnopqrst +abcdefghijklmnopqrstu +abcdefghijklmnopqrstuv +abcdefghijklmnopqrstuvw +abcdefghijklmnopqrstuvwx +abcdefghijklmnopqrstuvwxy +abcdefghijklmnopqrstuvwxyz +abcdefghijklmnopqrstuvwxyzA +abcdefghijklmnopqrstuvwxyzAB +abcdefghijklmnopqrstuvwxyzABC +abcdefghijklmnopqrstuvwxyzABCD +abcdefghijklmnopqrstuvwxyzABCDE +abcdefghijklmnopqrstuvwxyzABCDEF +abcdefghijklmnopqrstuvwxyzABCDEFG +abcdefghijklmnopqrstuvwxyzABCDEFGH +abcdefghijklmnopqrstuvwxyzABCDEFGHI +abcdefghijklmnopqrstuvwxyzABCDEFGHIJ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJK +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKL +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLM +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRST +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTU +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890a +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890ab +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abc +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcd +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcde +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdef +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefg +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghij +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijk +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijkl +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmn +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqr +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrs +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrst diff --git a/xterm.js/fixtures/escape_sequence_files/t0003-line_wrap.text b/xterm.js/fixtures/escape_sequence_files/t0003-line_wrap.text new file mode 100644 index 0000000..fbe1c56 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0003-line_wrap.text @@ -0,0 +1,25 @@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890a +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890ab +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abc +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcd +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcde +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdef +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefg +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghij +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijk +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijkl +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmn +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +r +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +rs +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +rst + diff --git a/xterm.js/fixtures/escape_sequence_files/t0003j-LF.in b/xterm.js/fixtures/escape_sequence_files/t0003j-LF.in new file mode 100644 index 0000000..9f52852 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0003j-LF.in @@ -0,0 +1,26 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 diff --git a/xterm.js/fixtures/escape_sequence_files/t0003j-LF.text b/xterm.js/fixtures/escape_sequence_files/t0003j-LF.text new file mode 100644 index 0000000..a6210e1 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0003j-LF.text @@ -0,0 +1,25 @@ +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 + diff --git a/xterm.js/fixtures/escape_sequence_files/t0004-LF.in b/xterm.js/fixtures/escape_sequence_files/t0004-LF.in new file mode 100644 index 0000000..4f4aa53 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0004-LF.in @@ -0,0 +1,83 @@ +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +A +B +C +D +E +F +G +H +I +J +K +L +M +N +O +P +Q +R +S +T +U +V +W +X +Y +Z +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0 +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t diff --git a/xterm.js/fixtures/escape_sequence_files/t0004-LF.text b/xterm.js/fixtures/escape_sequence_files/t0004-LF.text new file mode 100644 index 0000000..3756aca --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0004-LF.text @@ -0,0 +1,25 @@ +7 +8 +9 +0 +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t + diff --git a/xterm.js/fixtures/escape_sequence_files/t0004j-CR.in b/xterm.js/fixtures/escape_sequence_files/t0004j-CR.in new file mode 100644 index 0000000..d40432d --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0004j-CR.in @@ -0,0 +1,7 @@ +1 x + 2 x + 3 x + 4 x + 5 x + 6 x + 7 x \ No newline at end of file diff --git a/xterm.js/fixtures/escape_sequence_files/t0004j-CR.text b/xterm.js/fixtures/escape_sequence_files/t0004j-CR.text new file mode 100644 index 0000000..beb0e35 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0004j-CR.text @@ -0,0 +1,25 @@ +x +x2 +x 3 +x 4 +x 5 +x 6 +x 7 + + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0005-CR.in b/xterm.js/fixtures/escape_sequence_files/t0005-CR.in new file mode 100644 index 0000000..d5f545a --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0005-CR.in @@ -0,0 +1,82 @@ +b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a + b a diff --git a/xterm.js/fixtures/escape_sequence_files/t0005-CR.text b/xterm.js/fixtures/escape_sequence_files/t0005-CR.text new file mode 100644 index 0000000..dfcc049 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0005-CR.text @@ -0,0 +1,25 @@ +a b +a b +a b +a b +a b +a b +a b +a b +a b +a b +a b +a b +a b +a b +a b +a b +a b +a b +a b +a b + +a + +ab + diff --git a/xterm.js/fixtures/escape_sequence_files/t0006-IND.in b/xterm.js/fixtures/escape_sequence_files/t0006-IND.in new file mode 100644 index 0000000..614552f --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0006-IND.in @@ -0,0 +1 @@ +aDbDcDdDeDfDgDhDiDjDkDlDmDnDoDpDqDrDsDtDuDvDwDxDyDzDADBDCDDDEDFDGDHDIDJDKDLDMDNDODPDQDRDSDTDUDVDWDXDYDZD0D1D2D3D4D5D6D7D8D9D0DaDbDcDdDeDfDgDhDiDjDkDlDmDnDoDpDqDrDsDt diff --git a/xterm.js/fixtures/escape_sequence_files/t0006-IND.text b/xterm.js/fixtures/escape_sequence_files/t0006-IND.text new file mode 100644 index 0000000..8c69a7f --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0006-IND.text @@ -0,0 +1,25 @@ + 7 + 8 + 9 + 0 + a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r + s + t + diff --git a/xterm.js/fixtures/escape_sequence_files/t0007-space_at_end.in b/xterm.js/fixtures/escape_sequence_files/t0007-space_at_end.in new file mode 100644 index 0000000..73d19c5 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0007-space_at_end.in @@ -0,0 +1,8 @@ +0 space: +1 space: +2 space: +3 space: +70 space: +71 space: +72 space: +73 space: diff --git a/xterm.js/fixtures/escape_sequence_files/t0007-space_at_end.text b/xterm.js/fixtures/escape_sequence_files/t0007-space_at_end.text new file mode 100644 index 0000000..f46caee --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0007-space_at_end.text @@ -0,0 +1,25 @@ +0 space: +1 space: +2 space: +3 space: +70 space: +71 space: +72 space: + +73 space: + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0008-BS.in b/xterm.js/fixtures/escape_sequence_files/t0008-BS.in new file mode 100644 index 0000000..0980d87 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0008-BS.in @@ -0,0 +1,7 @@ +abcdefghijklmnopqrstuvwxyz! +abc@ +# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop$ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq% +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqr^ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrs& diff --git a/xterm.js/fixtures/escape_sequence_files/t0008-BS.text b/xterm.js/fixtures/escape_sequence_files/t0008-BS.text new file mode 100644 index 0000000..77d1710 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0008-BS.text @@ -0,0 +1,25 @@ +abcdefghijklmnopqrst!vwxyz +@bc +# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghij$lmnop +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghij%lmnopq +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +^ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +&s + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0009-NEL.in b/xterm.js/fixtures/escape_sequence_files/t0009-NEL.in new file mode 100644 index 0000000..b541ec4 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0009-NEL.in @@ -0,0 +1 @@ +aEabEabcEabcdEabcdeEabcdefEabcdefgEabcdefghEabcdefghiEabcdefghijEabcdefghijkEabcdefghijklEabcdefghijklmEabcdefghijklmnEabcdefghijklmnoEabcdefghijklmnopEabcdefghijklmnopqEabcdefghijklmnopqrEabcdefghijklmnopqrsEabcdefghijklmnopqrstEabcdefghijklmnopqrstuEabcdefghijklmnopqrstuvEabcdefghijklmnopqrstuvwEabcdefghijklmnopqrstuvwxEabcdefghijklmnopqrstuvwxyEabcdefghijklmnopqrstuvwxyzEabcdefghijklmnopqrstuvwxyzAEabcdefghijklmnopqrstuvwxyzABEabcdefghijklmnopqrstuvwxyzABCEabcdefghijklmnopqrstuvwxyzABCDEabcdefghijklmnopqrstuvwxyzABCDEEabcdefghijklmnopqrstuvwxyzABCDEFEabcdefghijklmnopqrstuvwxyzABCDEFGEabcdefghijklmnopqrstuvwxyzABCDEFGHEabcdefghijklmnopqrstuvwxyzABCDEFGHIEabcdefghijklmnopqrstuvwxyzABCDEFGHIJEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQREabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890EabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890aEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdeEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghiEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijkEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnoEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrsEabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqrst diff --git a/xterm.js/fixtures/escape_sequence_files/t0009-NEL.text b/xterm.js/fixtures/escape_sequence_files/t0009-NEL.text new file mode 100644 index 0000000..fbe1c56 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0009-NEL.text @@ -0,0 +1,25 @@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890a +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890ab +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abc +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcd +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcde +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdef +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefg +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghij +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijk +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijkl +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmn +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +r +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +rs +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +rst + diff --git a/xterm.js/fixtures/escape_sequence_files/t0010-RI.in b/xterm.js/fixtures/escape_sequence_files/t0010-RI.in new file mode 100644 index 0000000..c2aeb67 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0010-RI.in @@ -0,0 +1,10 @@ +a +b +c +dMeMfMg +h +i +j....................................................................kMlMmMn + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0010-RI.text b/xterm.js/fixtures/escape_sequence_files/t0010-RI.text new file mode 100644 index 0000000..5320654 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0010-RI.text @@ -0,0 +1,25 @@ +a g n +h f m +ie l +j....................................................................k + + + + + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0011-RI_scroll.in b/xterm.js/fixtures/escape_sequence_files/t0011-RI_scroll.in new file mode 100644 index 0000000..14da12d --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0011-RI_scroll.in @@ -0,0 +1,47 @@ +And the third. + + + + + + + + + + + + + + + + + + + + +This should be the last line. +This one should be lost. +This one's a goner, too. MMMMMMMMMMMMMMMMMMMMMMMMThis is second line. MThis should be the first line. + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0011-RI_scroll.text b/xterm.js/fixtures/escape_sequence_files/t0011-RI_scroll.text new file mode 100644 index 0000000..21cb1cf --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0011-RI_scroll.text @@ -0,0 +1,25 @@ +This should be the first line. +This is second line. +And the third. + + + + + + + + + + + + + + + + + + + + +This should be the last line. +This one should be lost. diff --git a/xterm.js/fixtures/escape_sequence_files/t0012-VT.in b/xterm.js/fixtures/escape_sequence_files/t0012-VT.in new file mode 100644 index 0000000..ee56208 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0012-VT.in @@ -0,0 +1 @@ +a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t \ No newline at end of file diff --git a/xterm.js/fixtures/escape_sequence_files/t0012-VT.text b/xterm.js/fixtures/escape_sequence_files/t0012-VT.text new file mode 100644 index 0000000..8c69a7f --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0012-VT.text @@ -0,0 +1,25 @@ + 7 + 8 + 9 + 0 + a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r + s + t + diff --git a/xterm.js/fixtures/escape_sequence_files/t0013-FF.in b/xterm.js/fixtures/escape_sequence_files/t0013-FF.in new file mode 100644 index 0000000..01198c2 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0013-FF.in @@ -0,0 +1 @@ +a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t diff --git a/xterm.js/fixtures/escape_sequence_files/t0013-FF.text b/xterm.js/fixtures/escape_sequence_files/t0013-FF.text new file mode 100644 index 0000000..16c9c2b --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0013-FF.text @@ -0,0 +1,25 @@ + 8 + 9 + 0 + a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r + s + t + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0014-CAN.in b/xterm.js/fixtures/escape_sequence_files/t0014-CAN.in new file mode 100644 index 0000000..64bae4a --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0014-CAN.in @@ -0,0 +1,8 @@ +abcdDefgh +abcdDefgh +abcd!Defgh +abcd!*Defgh +abcd[Defgh +abcd[!Defgh +abcd[2Defgh +abcd[*2;Defgh diff --git a/xterm.js/fixtures/escape_sequence_files/t0014-CAN.text b/xterm.js/fixtures/escape_sequence_files/t0014-CAN.text new file mode 100644 index 0000000..77a38fa --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0014-CAN.text @@ -0,0 +1,25 @@ +abcdDefgh +abcdDefgh +abcdDefgh +abcdDefgh +abcdDefgh +abcdDefgh +abcdDefgh +abcdDefgh + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0015-SUB.in b/xterm.js/fixtures/escape_sequence_files/t0015-SUB.in new file mode 100644 index 0000000..1bd237f --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0015-SUB.in @@ -0,0 +1,8 @@ +abcdDefgh +abcdDefgh +abcd!Defgh +abcd!*Defgh +abcd[Defgh +abcd[!Defgh +abcd[2Defgh +abcd[*2;Defgh diff --git a/xterm.js/fixtures/escape_sequence_files/t0015-SUB.text b/xterm.js/fixtures/escape_sequence_files/t0015-SUB.text new file mode 100644 index 0000000..77a38fa --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0015-SUB.text @@ -0,0 +1,25 @@ +abcdDefgh +abcdDefgh +abcdDefgh +abcdDefgh +abcdDefgh +abcdDefgh +abcdDefgh +abcdDefgh + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0016-SU.in b/xterm.js/fixtures/escape_sequence_files/t0016-SU.in new file mode 100644 index 0000000..7e52573 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0016-SU.in @@ -0,0 +1,17 @@ +HelloGoodbye + +UpDown +x + +-----------------------------------------------------------------------------x +------------------------------------------------------------------------------x +-------------------------------------------------------------------------------x +--------------------------------------------------------------------------------x +---------------------------------------------------------------------------------x +.............................................................................x +..............................................................................x +...............................................................................x +................................................................................x +.................................................................................x + +The End. diff --git a/xterm.js/fixtures/escape_sequence_files/t0016-SU.text b/xterm.js/fixtures/escape_sequence_files/t0016-SU.text new file mode 100644 index 0000000..2323fa3 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0016-SU.text @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + +The End. + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0017-SD.in b/xterm.js/fixtures/escape_sequence_files/t0017-SD.in new file mode 100644 index 0000000..ce76440 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0017-SD.in @@ -0,0 +1,54 @@ +A + B + C + D + E + F + G + H + I + J + K + L + M + N + O + P + Q + R + S + T + U + V + W + X +a + b + c + d + e + f + g + h +------------------------------------------------------------------------------1 + + +-------------------------------------------------------------------------------2 + + +--------------------------------------------------------------------------------3 + + +---------------------------------------------------------------------------------4 + + +..............................................................................5 + + +...............................................................................6 + + +................................................................................7 + + +.................................................................................8 diff --git a/xterm.js/fixtures/escape_sequence_files/t0017-SD.text b/xterm.js/fixtures/escape_sequence_files/t0017-SD.text new file mode 100644 index 0000000..6e39cd9 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0017-SD.text @@ -0,0 +1,25 @@ + + +a + b + f + g + h 1 + + 2 + + +3 + + +-4------------------------------------------------------------------------------ + + 5 + + 6 + + 7 + + +8............................................................................... + diff --git a/xterm.js/fixtures/escape_sequence_files/t0020-CUF.in b/xterm.js/fixtures/escape_sequence_files/t0020-CUF.in new file mode 100644 index 0000000..9df6cd7 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0020-CUF.in @@ -0,0 +1,14 @@ +abcdefghijkl +abcdefghijkl +abcdefghijkl +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqr@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@ +x +x +abcd diff --git a/xterm.js/fixtures/escape_sequence_files/t0020-CUF.text b/xterm.js/fixtures/escape_sequence_files/t0020-CUF.text new file mode 100644 index 0000000..b868261 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0020-CUF.text @@ -0,0 +1,25 @@ +abcdefg hijkl +abcdefg hijkl +abcdefg hijkl +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno @ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +r @ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @ + x + x +abcd + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0021-CUB.in b/xterm.js/fixtures/escape_sequence_files/t0021-CUB.in new file mode 100644 index 0000000..b07f753 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0021-CUB.in @@ -0,0 +1,8 @@ +abcdefg!@ +abcdefg!@ +abcdefg!@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqr@ +x diff --git a/xterm.js/fixtures/escape_sequence_files/t0021-CUB.text b/xterm.js/fixtures/escape_sequence_files/t0021-CUB.text new file mode 100644 index 0000000..9a1b385 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0021-CUB.text @@ -0,0 +1,25 @@ +abcdef!@ +!@cdefg +abcde!@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmn@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@q +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +@ +x + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0022-CUU.in b/xterm.js/fixtures/escape_sequence_files/t0022-CUU.in new file mode 100644 index 0000000..4c47f30 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0022-CUU.in @@ -0,0 +1,25 @@ +a +b +c +defg +h +i +j....................................................................klmn + + + + + + + + + + + +0123 + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0022-CUU.text b/xterm.js/fixtures/escape_sequence_files/t0022-CUU.text new file mode 100644 index 0000000..b786ade --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0022-CUU.text @@ -0,0 +1,25 @@ +a g n +h f m +ie l +j....................................................................k + + 3 + + + 2 + + 1 +0 + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0023-CUU_scroll.in b/xterm.js/fixtures/escape_sequence_files/t0023-CUU_scroll.in new file mode 100644 index 0000000..e0c9243 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0023-CUU_scroll.in @@ -0,0 +1,50 @@ +This is the first line. +This is the second line. +And the third. +This line should be deleted. + + + + + + + + + + + + + + + + + + + + + +Penultimate line. +This should be the last line. I have gone up all the way... + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0023-CUU_scroll.text b/xterm.js/fixtures/escape_sequence_files/t0023-CUU_scroll.text new file mode 100644 index 0000000..96b8726 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0023-CUU_scroll.text @@ -0,0 +1,25 @@ +I have gone up all the way... +This line should be deleted. + + + + + + + + + + + + + + + + + + + + + +Penultimate line. +This should be the last line. diff --git a/xterm.js/fixtures/escape_sequence_files/t0024-CUD.in b/xterm.js/fixtures/escape_sequence_files/t0024-CUD.in new file mode 100644 index 0000000..e971bbe --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0024-CUD.in @@ -0,0 +1,24 @@ +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x012345Bottom line. ABCDE  diff --git a/xterm.js/fixtures/escape_sequence_files/t0024-CUD.text b/xterm.js/fixtures/escape_sequence_files/t0024-CUD.text new file mode 100644 index 0000000..622c0b0 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0024-CUD.text @@ -0,0 +1,25 @@ +b 1 +c 2 +d 3 +e +f 4 +g +h +i 5 +j +k +l +m +n +o +p +q A +r B +s C +t D +u E +v +w +x + Bottom line. + diff --git a/xterm.js/fixtures/escape_sequence_files/t0025-CUP.in b/xterm.js/fixtures/escape_sequence_files/t0025-CUP.in new file mode 100644 index 0000000..b62631e --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0025-CUP.in @@ -0,0 +1 @@ +abcdefg diff --git a/xterm.js/fixtures/escape_sequence_files/t0025-CUP.text b/xterm.js/fixtures/escape_sequence_files/t0025-CUP.text new file mode 100644 index 0000000..44dc619 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0025-CUP.text @@ -0,0 +1,25 @@ + b + + +e + + + + + d + + + + + + + + + + g + + + + + f + diff --git a/xterm.js/fixtures/escape_sequence_files/t0026-CNL.in b/xterm.js/fixtures/escape_sequence_files/t0026-CNL.in new file mode 100644 index 0000000..8318682 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0026-CNL.in @@ -0,0 +1,2 @@ +abcdefghi +-------------------------------------------------------------------------abcdefghijlast line diff --git a/xterm.js/fixtures/escape_sequence_files/t0026-CNL.text b/xterm.js/fixtures/escape_sequence_files/t0026-CNL.text new file mode 100644 index 0000000..61ac27e --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0026-CNL.text @@ -0,0 +1,25 @@ +def + + + + +ghi +-------------------------------------------------------------------------abcdefg +hij + + + + + + + + + + + + + + + +last line + diff --git a/xterm.js/fixtures/escape_sequence_files/t0027-CPL.in b/xterm.js/fixtures/escape_sequence_files/t0027-CPL.in new file mode 100644 index 0000000..edafc49 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0027-CPL.in @@ -0,0 +1,6 @@ +erasedreplacement + + +line fourline two + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0027-CPL.text b/xterm.js/fixtures/escape_sequence_files/t0027-CPL.text new file mode 100644 index 0000000..847ed7c --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0027-CPL.text @@ -0,0 +1,25 @@ +replacement +line two + +line four + + + + + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0030-HPR.in b/xterm.js/fixtures/escape_sequence_files/t0030-HPR.in new file mode 100644 index 0000000..485720f --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0030-HPR.in @@ -0,0 +1,14 @@ +abcdefghijkl +abcdefghijkl +abcdefghijkl +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqr@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm@ +x +x +abcd diff --git a/xterm.js/fixtures/escape_sequence_files/t0030-HPR.text b/xterm.js/fixtures/escape_sequence_files/t0030-HPR.text new file mode 100644 index 0000000..b868261 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0030-HPR.text @@ -0,0 +1,25 @@ +abcdefg hijkl +abcdefg hijkl +abcdefg hijkl +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno @ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +r @ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklm @ + x + x +abcd + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0031-HPB.in_ b/xterm.js/fixtures/escape_sequence_files/t0031-HPB.in_ new file mode 100644 index 0000000..13de738 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0031-HPB.in_ @@ -0,0 +1,8 @@ +abcdefg!@ +abcdefg!@ +abcdefg!@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopqr@ +x diff --git a/xterm.js/fixtures/escape_sequence_files/t0031-HPB.text b/xterm.js/fixtures/escape_sequence_files/t0031-HPB.text new file mode 100644 index 0000000..9ec4087 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0031-HPB.text @@ -0,0 +1,25 @@ +abcdefg!@ +abcdefg!@ +abcdefg!@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmno@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq +r@ +x + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0032-VPB.in b/xterm.js/fixtures/escape_sequence_files/t0032-VPB.in new file mode 100644 index 0000000..30dd002 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0032-VPB.in @@ -0,0 +1,25 @@ +a +b +c +defg +h +i +j....................................................................klmn + + + + + + + + + + + +0123 + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0032-VPB.text b/xterm.js/fixtures/escape_sequence_files/t0032-VPB.text new file mode 100644 index 0000000..15f0d67 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0032-VPB.text @@ -0,0 +1,25 @@ +b +c +defg +h +i +j....................................................................klmn + + + + + + + + + + + +0123 + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0033-VPB_scroll.in b/xterm.js/fixtures/escape_sequence_files/t0033-VPB_scroll.in new file mode 100644 index 0000000..f58db4b --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0033-VPB_scroll.in @@ -0,0 +1,50 @@ +This is the first line. +This is the second line. +And the third. +This line should be deleted. + + + + + + + + + + + + + + + + + + + + + +Penultimate line. +This should be the last line. I have gone up all the way... + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0033-VPB_scroll.text b/xterm.js/fixtures/escape_sequence_files/t0033-VPB_scroll.text new file mode 100644 index 0000000..0b20185 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0033-VPB_scroll.text @@ -0,0 +1,25 @@ +I have gone up all the way... + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0034-VPR.in b/xterm.js/fixtures/escape_sequence_files/t0034-VPR.in new file mode 100644 index 0000000..b9dc145 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0034-VPR.in @@ -0,0 +1,24 @@ +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x012345Bottom line. ABCDE  diff --git a/xterm.js/fixtures/escape_sequence_files/t0034-VPR.text b/xterm.js/fixtures/escape_sequence_files/t0034-VPR.text new file mode 100644 index 0000000..622c0b0 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0034-VPR.text @@ -0,0 +1,25 @@ +b 1 +c 2 +d 3 +e +f 4 +g +h +i 5 +j +k +l +m +n +o +p +q A +r B +s C +t D +u E +v +w +x + Bottom line. + diff --git a/xterm.js/fixtures/escape_sequence_files/t0035-HVP.in b/xterm.js/fixtures/escape_sequence_files/t0035-HVP.in new file mode 100644 index 0000000..781dfdb --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0035-HVP.in @@ -0,0 +1 @@ +abcdefg diff --git a/xterm.js/fixtures/escape_sequence_files/t0035-HVP.text b/xterm.js/fixtures/escape_sequence_files/t0035-HVP.text new file mode 100644 index 0000000..44dc619 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0035-HVP.text @@ -0,0 +1,25 @@ + b + + +e + + + + + d + + + + + + + + + + g + + + + + f + diff --git a/xterm.js/fixtures/escape_sequence_files/t0040-REP.in b/xterm.js/fixtures/escape_sequence_files/t0040-REP.in new file mode 100644 index 0000000..f1abf45 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0040-REP.in @@ -0,0 +1,7 @@ +x +< +abcdefg +abcdefg! + @ + . + ?- diff --git a/xterm.js/fixtures/escape_sequence_files/t0040-REP.text b/xterm.js/fixtures/escape_sequence_files/t0040-REP.text new file mode 100644 index 0000000..cae1ef9 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0040-REP.text @@ -0,0 +1,25 @@ +xxxxxx +< +abcdefg +abcd!fg + @@@@@@@@@ +@@@@@@@@@@@@ + . +.... + ? +?- + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0050-ICH.in b/xterm.js/fixtures/escape_sequence_files/t0050-ICH.in new file mode 100644 index 0000000..a629f20 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0050-ICH.in @@ -0,0 +1,23 @@ +abcdefghijklmnopqrstuvwxyz[15@ +abcdefghijklmnopqrstuvwxyz[80@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[17@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[18@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[19@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[20@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[21@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop[5@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq[5@ +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq[5@ +ICH at end:[5@ + +abcdefghijklmnopqrstuvwxyz[15@!@# +abcdefghijklmnopqrstuvwxyz[80@!@# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[17@!@# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[18@!@# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[19@!@# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[20@!@# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[21@!@# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop[5@!@# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq[5@!@# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnopq[5@!@# +ICH at end:[5@!@# diff --git a/xterm.js/fixtures/escape_sequence_files/t0050-ICH.text b/xterm.js/fixtures/escape_sequence_files/t0050-ICH.text new file mode 100644 index 0000000..d787b8d --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0050-ICH.text @@ -0,0 +1,25 @@ +abcdefghijklmnopqrstu +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567 89 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567 89 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567 8 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW XYZ01234567890abcdefghijkl +ICH at end: + +abcdefghijklmnopqrstu!@# vwxyz +abcdefghijklmnopqrstu!@# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567!@# 89 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567!@# 89 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567!@# 8 +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567!@# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567!@# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop! +@# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghijklmnop! +@# +abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW!@# XYZ01234567890abcdefghijkl +ICH at end:!@# + diff --git a/xterm.js/fixtures/escape_sequence_files/t0051-IL.in b/xterm.js/fixtures/escape_sequence_files/t0051-IL.in new file mode 100644 index 0000000..e66a242 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0051-IL.in @@ -0,0 +1,23 @@ +ab +cd +ef +gh +ij +kl +mn +opQRST +1 +2 +3 +4 +5------------------------------------------------------------------------------ab +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 diff --git a/xterm.js/fixtures/escape_sequence_files/t0051-IL.text b/xterm.js/fixtures/escape_sequence_files/t0051-IL.text new file mode 100644 index 0000000..2d0f595 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0051-IL.text @@ -0,0 +1,25 @@ + +ef +gh +ij +QR +kl +mn +op +1 +2 +3 +b +4------------------------------------------------------------------------------a +5 +6 +7 +8 +9 +10 + + + +11 +12 + diff --git a/xterm.js/fixtures/escape_sequence_files/t0052-DL.in b/xterm.js/fixtures/escape_sequence_files/t0052-DL.in new file mode 100644 index 0000000..b5a5fe0 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0052-DL.in @@ -0,0 +1,15 @@ +a +b +c +d +e +f +g +hijklmnop + + +1 +2 +3 +4 x + diff --git a/xterm.js/fixtures/escape_sequence_files/t0052-DL.text b/xterm.js/fixtures/escape_sequence_files/t0052-DL.text new file mode 100644 index 0000000..10d24aa --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0052-DL.text @@ -0,0 +1,25 @@ +a +b +c +ijklmnop +g +h +1 +x +4 + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0053-DCH.in b/xterm.js/fixtures/escape_sequence_files/t0053-DCH.in new file mode 100644 index 0000000..d1f8807 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0053-DCH.in @@ -0,0 +1,12 @@ +abcdefghijklmnopqrstuvwxyz> +abcdefghijklmnopqrstuvwxyz>! +abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh>! +abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh>! +------------------------------------------------------------------------------? +-------------------------------------------------------------------------------? +-------------------------------------------------------------------------------? +---------------------------------------------------------------------------------? +.............................................................................. +............................................................................... +............................................................................... +................................................................................. diff --git a/xterm.js/fixtures/escape_sequence_files/t0053-DCH.text b/xterm.js/fixtures/escape_sequence_files/t0053-DCH.text new file mode 100644 index 0000000..75c6b3b --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0053-DCH.text @@ -0,0 +1,25 @@ +abcdefghijklmnopqr>vwxyz +abcdefghijklmnopqr>!wxyz +>!mnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh +abcdefghijklmnopqrstuvwxyz0123456789ABC>!PQRSTUVWXYZ0123456789abcdefgh +------------------------------------------------------------------------------? +-------------------------------------------------------------------------------? +-------------------------------------------------------------------------------? +-------------------------------------------------------------------------------- +-? +.............................................................................. +............................................................................... +............................................................................... +................................................................................ +. + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0054-ECH.in b/xterm.js/fixtures/escape_sequence_files/t0054-ECH.in new file mode 100644 index 0000000..03a00d8 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0054-ECH.in @@ -0,0 +1,12 @@ +abcdefghijklmnopqrstuvwxyz> +abcdefghijklmnopqrstuvwxyz>! +abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh>! +abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh>! +------------------------------------------------------------------------------? +-------------------------------------------------------------------------------? +-------------------------------------------------------------------------------? +---------------------------------------------------------------------------------? +.............................................................................. +............................................................................... +............................................................................... +................................................................................. diff --git a/xterm.js/fixtures/escape_sequence_files/t0054-ECH.text b/xterm.js/fixtures/escape_sequence_files/t0054-ECH.text new file mode 100644 index 0000000..a22cfbe --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0054-ECH.text @@ -0,0 +1,25 @@ +abcdefghijklmnopqr> vwxyz +abcdefghijklmnopqr>! vwxyz +>! lmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh +abcdefghijklmnopqrstuvwxyz0123456789ABC>! OPQRSTUVWXYZ0123456789abcdefgh +------------------------------------------------------------------------------? +-------------------------------------------------------------------------------? +-------------------------------------------------------------------------------? +-------------------------------------------------------------------------------- +-? +.............................................................................. +............................................................................... +............................................................................... +................................................................................ +. + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0055-EL.in b/xterm.js/fixtures/escape_sequence_files/t0055-EL.in new file mode 100644 index 0000000..014658c --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0055-EL.in @@ -0,0 +1,8 @@ +abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh>< +abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh>< +abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh>< +abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh>< +abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh><! +abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh><! +abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh><! +abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh! diff --git a/xterm.js/fixtures/escape_sequence_files/t0055-EL.text b/xterm.js/fixtures/escape_sequence_files/t0055-EL.text new file mode 100644 index 0000000..a248f3b --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0055-EL.text @@ -0,0 +1,25 @@ +abcdefghijklmnopqrstuvwxyz0123456789ABC> +abcdefghijklmnopqrstuvwxyz0123456789ABC> + FGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh + +abcdefghijklmnopqrstuvwxyz0123456789ABC>! + !FGHIJKLMNOPQRSTUVWXYZ0123456789abcdefgh + ! +abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefg! + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0056-ED.in b/xterm.js/fixtures/escape_sequence_files/t0056-ED.in new file mode 100644 index 0000000..fca4e54 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0056-ED.in @@ -0,0 +1,62 @@ +a +ab +abc +abcd +abcde +abcdef +abcdefg +abcdefgh +abcdefghi +abcdefghij +abcdefghijk +abcdefghijkl +abcdefghijklm +abcdefghijklmn +abcdefghijklmno +abcdefghijklmnop +abcdefghijklmnopq +abcdefghijklmnopqr +abcdefghijklmnopqrs +abcdefghijklmnopqrst +abcdefghijklmnopqrstu +abcdefghijklmnopqrstuv +abcdefghijklmnopqrstuvw +abcdefghijklmnopqrstuvwx +abcdefghijklmnopqrstuvwxy +abcdefghijklmnopqrstuvwxyz +A +AB +ABC +ABCD +ABCDE +ABCDEF +ABCDEFG +ABCDEFGH +ABCDEFGHI +ABCDEFGHIJ +ABCDEFGHIJK +ABCDEFGHIJKL +ABCDEFGHIJKLM +ABCDEFGHIJKLMN +ABCDEFGHIJKLMNO +ABCDEFGHIJKLMNOP +ABCDEFGHIJKLMNOPQ +ABCDEFGHIJKLMNOPQR +ABCDEFGHIJKLMNOPQRS +ABCDEFGHIJKLMNOPQRST +ABCDEFGHIJKLMNOPQRSTU +ABCDEFGHIJKLMNOPQRSTUV +ABCDEFGHIJKLMNOPQRSTUVW +ABCDEFGHIJKLMNOPQRSTUVWX +ABCDEFGHIJKLMNOPQRSTUVWXY! + +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaav^ + + + +the end diff --git a/xterm.js/fixtures/escape_sequence_files/t0056-ED.text b/xterm.js/fixtures/escape_sequence_files/t0056-ED.text new file mode 100644 index 0000000..61a8ac7 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0056-ED.text @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + ! + +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaav +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^ + + + +the end + diff --git a/xterm.js/fixtures/escape_sequence_files/t0057-ED3.in b/xterm.js/fixtures/escape_sequence_files/t0057-ED3.in new file mode 100644 index 0000000..46606df --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0057-ED3.in @@ -0,0 +1,55 @@ +a +ab +abc +abcd +abcde +abcdef +abcdefg +abcdefgh +abcdefghi +abcdefghij +abcdefghijk +abcdefghijkl +abcdefghijklm +abcdefghijklmn +abcdefghijklmno +abcdefghijklmnop +abcdefghijklmnopq +abcdefghijklmnopqr +abcdefghijklmnopqrs +abcdefghijklmnopqrst +abcdefghijklmnopqrstu +abcdefghijklmnopqrstuv +abcdefghijklmnopqrstuvw +abcdefghijklmnopqrstuvwx +abcdefghijklmnopqrstuvwxy +abcdefghijklmnopqrstuvwxyz +A +AB +ABC +ABCD +ABCDE +ABCDEF +ABCDEFG +ABCDEFGH +ABCDEFGHI +ABCDEFGHIJ +ABCDEFGHIJK +ABCDEFGHIJKL +ABCDEFGHIJKLM +ABCDEFGHIJKLMN +ABCDEFGHIJKLMNO +ABCDEFGHIJKLMNOP +ABCDEFGHIJKLMNOPQ +ABCDEFGHIJKLMNOPQR +ABCDEFGHIJKLMNOPQRS +ABCDEFGHIJKLMNOPQRST +ABCDEFGHIJKLMNOPQRSTU +ABCDEFGHIJKLMNOPQRSTUV +ABCDEFGHIJKLMNOPQRSTUVW +ABCDEFGHIJKLMNOPQRSTUVWX +ABCDEFGHIJKLMNOPQRSTUVWXY +this +is +the +end diff --git a/xterm.js/fixtures/escape_sequence_files/t0057-ED3.note b/xterm.js/fixtures/escape_sequence_files/t0057-ED3.note new file mode 100644 index 0000000..ca6d940 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0057-ED3.note @@ -0,0 +1,6 @@ +Xterm behaves oddly with CSI 3 J. This function is supposed to clear the +saved lines in history. Xterm does this, but a small number of lines of +history are not cleared. The number seems to vary with how high the window is +and how much output has recently been saved. There is no reason to simulate +this behavior, so the expected outputs are as if the entire history was +erased. diff --git a/xterm.js/fixtures/escape_sequence_files/t0057-ED3.text b/xterm.js/fixtures/escape_sequence_files/t0057-ED3.text new file mode 100644 index 0000000..8230921 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0057-ED3.text @@ -0,0 +1,25 @@ +ABCDEF +ABCDEFG +ABCDEFGH +ABCDEFGHI +ABCDEFGHIJ +ABCDEFGHIJK +ABCDEFGHIJKL +ABCDEFGHIJKLM +ABCDEFGHIJKLMN +ABCDEFGHIJKLMNO +ABCDEFGHIJKLMNOP +ABCDEFGHIJKLMNOPQ +ABCDEFGHIJKLMNOPQR +ABCDEFGHIJKLMNOPQRS +ABCDEFGHIJKLMNOPQRST +ABCDEFGHIJKLMNOPQRSTU +ABCDEFGHIJKLMNOPQRSTUV +ABCDEFGHIJKLMNOPQRSTUVW +ABCDEFGHIJKLMNOPQRSTUVWX +ABCDEFGHIJKLMNOPQRSTUVWXY +this +is +the +end + diff --git a/xterm.js/fixtures/escape_sequence_files/t0060-DECSC.in b/xterm.js/fixtures/escape_sequence_files/t0060-DECSC.in new file mode 100644 index 0000000..d269150 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0060-DECSC.in @@ -0,0 +1,9 @@ + 7v 12 + +38^ + + + + v7 +...ooo8^ + diff --git a/xterm.js/fixtures/escape_sequence_files/t0060-DECSC.text b/xterm.js/fixtures/escape_sequence_files/t0060-DECSC.text new file mode 100644 index 0000000..409198b --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0060-DECSC.text @@ -0,0 +1,25 @@ + +3 + + v +... ^ + ooo + + + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0061-CSI_s.in b/xterm.js/fixtures/escape_sequence_files/t0061-CSI_s.in new file mode 100644 index 0000000..451fafa --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0061-CSI_s.in @@ -0,0 +1,9 @@ + v 12 + +3^ + + + + v +...ooo^ + diff --git a/xterm.js/fixtures/escape_sequence_files/t0061-CSI_s.text b/xterm.js/fixtures/escape_sequence_files/t0061-CSI_s.text new file mode 100644 index 0000000..409198b --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0061-CSI_s.text @@ -0,0 +1,25 @@ + +3 + + v +... ^ + ooo + + + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0070-DECSTBM_LF.in b/xterm.js/fixtures/escape_sequence_files/t0070-DECSTBM_LF.in new file mode 100644 index 0000000..571f223 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0070-DECSTBM_LF.in @@ -0,0 +1,31 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9ABCDEFa +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +uvwxyz + +The end. diff --git a/xterm.js/fixtures/escape_sequence_files/t0070-DECSTBM_LF.text b/xterm.js/fixtures/escape_sequence_files/t0070-DECSTBM_LF.text new file mode 100644 index 0000000..0940b07 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0070-DECSTBM_LF.text @@ -0,0 +1,25 @@ +1 + 2 + 6 + 7 + 8 + 9 ABC +DEF + a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p +yz qrstu vwx +The end. diff --git a/xterm.js/fixtures/escape_sequence_files/t0071-DECSTBM_IND.in b/xterm.js/fixtures/escape_sequence_files/t0071-DECSTBM_IND.in new file mode 100644 index 0000000..f9f6a42 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0071-DECSTBM_IND.in @@ -0,0 +1,3 @@ +1D2D3D4D5D6D7D8D9ABCDEFaDbDcDdDeDfDgDhDiDjDkDlDmDnDoDpDqDrDsDtDuvwxyz + +The end. diff --git a/xterm.js/fixtures/escape_sequence_files/t0071-DECSTBM_IND.text b/xterm.js/fixtures/escape_sequence_files/t0071-DECSTBM_IND.text new file mode 100644 index 0000000..f6644fb --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0071-DECSTBM_IND.text @@ -0,0 +1,25 @@ + 2 + 6 + 7 + 8 + 9 ABC +DEF + a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q +The end. rstu vwx + diff --git a/xterm.js/fixtures/escape_sequence_files/t0072-DECSTBM_NEL.in b/xterm.js/fixtures/escape_sequence_files/t0072-DECSTBM_NEL.in new file mode 100644 index 0000000..5df9e71 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0072-DECSTBM_NEL.in @@ -0,0 +1,2 @@ +1E2E3E4E5E6E7E8E9aEbEcEdEeEfEgEhEiEjEkElEmEnEoEpEqErEsEtEu +The end. diff --git a/xterm.js/fixtures/escape_sequence_files/t0072-DECSTBM_NEL.text b/xterm.js/fixtures/escape_sequence_files/t0072-DECSTBM_NEL.text new file mode 100644 index 0000000..1a0e4a1 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0072-DECSTBM_NEL.text @@ -0,0 +1,25 @@ +2 +5 +6 +7 +8 +9 + a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +The end. + diff --git a/xterm.js/fixtures/escape_sequence_files/t0073-DECSTBM_RI.in b/xterm.js/fixtures/escape_sequence_files/t0073-DECSTBM_RI.in new file mode 100644 index 0000000..fc7b7e4 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0073-DECSTBM_RI.in @@ -0,0 +1,43 @@ +TOP 1 +TOP 2 +TOP 3 +TOP 4 +TOP 5 +TOP 6 - GONE + + + + + + + + + + + + +BOTTOM 6 - GONE +BOTTOM 5 +BOTTOM 4 +BOTTOM 3 +BOTTOM 2 +BOTTOM 1 + + + + +And the third. + + + + + + + + + + +This should be the last line. +This one should be lost. +This one's a goner, too. MMMMMMMMMMMMMMThis is second line. MThis should be the first line. +The end. diff --git a/xterm.js/fixtures/escape_sequence_files/t0073-DECSTBM_RI.text b/xterm.js/fixtures/escape_sequence_files/t0073-DECSTBM_RI.text new file mode 100644 index 0000000..ce6dbc7 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0073-DECSTBM_RI.text @@ -0,0 +1,25 @@ +TOP 2 +TOP 3 +TOP 4 +TOP 5 +This should be the first line. +This is second line. +And the third. + + + + + + + + + + +This should be the last line. +BOTTOM 5 +BOTTOM 4 +BOTTOM 3 +BOTTOM 2 +BOTTOM 1 +The end. + diff --git a/xterm.js/fixtures/escape_sequence_files/t0074-DECSTBM_SU_SD.in b/xterm.js/fixtures/escape_sequence_files/t0074-DECSTBM_SU_SD.in new file mode 100644 index 0000000..1acbaf3 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0074-DECSTBM_SU_SD.in @@ -0,0 +1,24 @@ +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x diff --git a/xterm.js/fixtures/escape_sequence_files/t0074-DECSTBM_SU_SD.text b/xterm.js/fixtures/escape_sequence_files/t0074-DECSTBM_SU_SD.text new file mode 100644 index 0000000..948e5d4 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0074-DECSTBM_SU_SD.text @@ -0,0 +1,24 @@ +a + b + c + d + f + g + h + i + + j + k + l + m + + + + n + o + p + q + r + s + w + x diff --git a/xterm.js/fixtures/escape_sequence_files/t0075-DECSTBM_CUU_CUD.in b/xterm.js/fixtures/escape_sequence_files/t0075-DECSTBM_CUU_CUD.in new file mode 100644 index 0000000..b679113 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0075-DECSTBM_CUU_CUD.in @@ -0,0 +1,24 @@ +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x12 diff --git a/xterm.js/fixtures/escape_sequence_files/t0075-DECSTBM_CUU_CUD.text b/xterm.js/fixtures/escape_sequence_files/t0075-DECSTBM_CUU_CUD.text new file mode 100644 index 0000000..486b91d --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0075-DECSTBM_CUU_CUD.text @@ -0,0 +1,25 @@ +a +b +c +d +e +f +g +h +i +j2 +k +l +m +n +o +p +q +r +1 +t +u +v +w +x + diff --git a/xterm.js/fixtures/escape_sequence_files/t0076-DECSTBM_IL_DL.in b/xterm.js/fixtures/escape_sequence_files/t0076-DECSTBM_IL_DL.in new file mode 100644 index 0000000..58d20d2 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0076-DECSTBM_IL_DL.in @@ -0,0 +1,33 @@ + 1 (IL on line 2, expect nothing) + 2 (DL on line 22, expect nothing) + 3 vvvv IL on line 5, expected: A_BC + 4 A + 5 B + 6 C + 7 D + 8 ^^^^ + 9 vvvv DL on line 11, expected: ACD_ +10 A +11 B +12 C +13 D +14 ^^^^ +15 vvvv IL on line 17, expected: A_ +16 A +17 B +18 ^^^^ +19 vvvv IL on line 21, expected: A_ +20 A +21 B +22 ^^^^ +23 vvvv IL on line 24, expected: _A +24 A + +25 B +26 ^^^^ +27 vvvv DL on line 28, expected: B_ +28 A +29 B +30 ^^^^ +31 +32 diff --git a/xterm.js/fixtures/escape_sequence_files/t0076-DECSTBM_IL_DL.text b/xterm.js/fixtures/escape_sequence_files/t0076-DECSTBM_IL_DL.text new file mode 100644 index 0000000..92c1033 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0076-DECSTBM_IL_DL.text @@ -0,0 +1,25 @@ + 8 ^^^^ + 9 vvvv DL on line 11, expected: ACD_ +10 A +12 C +13 D + +14 ^^^^ +15 vvvv IL on line 17, expected: A_ +16 A + +18 ^^^^ +19 vvvv IL on line 21, expected: A_ +20 A + +22 ^^^^ + +23 vvvv IL on line 24, expected: _A +25 B +26 ^^^^ +28 A + +29 B +30 ^^^^ +31 +32 diff --git a/xterm.js/fixtures/escape_sequence_files/t0077-DECSTBM_quirks.in b/xterm.js/fixtures/escape_sequence_files/t0077-DECSTBM_quirks.in new file mode 100644 index 0000000..b444362 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0077-DECSTBM_quirks.in @@ -0,0 +1,32 @@ + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24A +B +C +D +E +F +G + +Done. diff --git a/xterm.js/fixtures/escape_sequence_files/t0077-DECSTBM_quirks.text b/xterm.js/fixtures/escape_sequence_files/t0077-DECSTBM_quirks.text new file mode 100644 index 0000000..ea142e3 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0077-DECSTBM_quirks.text @@ -0,0 +1,25 @@ + 3 + 4 + A + 5 + 7 + C + 8 + 9 +10 +11 +12 +13 +14 +18 +19 +20 +21 +23 +24 + B + D + F + G +Done. + diff --git a/xterm.js/fixtures/escape_sequence_files/t0080-HT.in b/xterm.js/fixtures/escape_sequence_files/t0080-HT.in new file mode 100644 index 0000000..581e0ba --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0080-HT.in @@ -0,0 +1,14 @@ +a b c d e f g h i j k l + x +1 2 + 3 + +Tab before EOL: +no tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh@ +tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh @ +tab (2):abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefg @ + +Tab at EOL: +no tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi@ +tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi @ +with clipping: 4567890abcdefghi MD@ diff --git a/xterm.js/fixtures/escape_sequence_files/t0080-HT.text b/xterm.js/fixtures/escape_sequence_files/t0080-HT.text new file mode 100644 index 0000000..0683c21 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0080-HT.text @@ -0,0 +1,25 @@ +a b c d e f g h i j k +l + x +1 3 2 + + +Tab before EOL: +no tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh@ +tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh@ +tab (2):abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefg @ + +Tab at EOL: +no tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi +@ +tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi +@ +with clipping: 4567890abcdefgh@ + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0081-TBC.in b/xterm.js/fixtures/escape_sequence_files/t0081-TBC.in new file mode 100644 index 0000000..744b7a5 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0081-TBC.in @@ -0,0 +1,19 @@ +default: +> 1 2 3 4 5 6 7 8 9 0 + +clear non-existant: x x +> 1 2 3 4 5 6 7 8 9 0 + +clear 2 and 4: x x +> 1 3 5 6 7 8 9 0 + +clear 0: x +> 1 3 5 6 7 8 9 0 + +clear after 0: .x +> 1 3 5 6 7 8 9 0 + +clear all: +> 0done + +TBC at end with clipping: ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdeMD! diff --git a/xterm.js/fixtures/escape_sequence_files/t0081-TBC.text b/xterm.js/fixtures/escape_sequence_files/t0081-TBC.text new file mode 100644 index 0000000..575e3fd --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0081-TBC.text @@ -0,0 +1,25 @@ +default: +> 1 2 3 4 5 6 7 8 9 0 + +clear non-existant: x x +> 1 2 3 4 5 6 7 8 9 0 + +clear 2 and 4: x x +> 1 3 5 6 7 8 9 0 + +clear 0: x +> 1 3 5 6 7 8 9 0 + +clear after 0: . +x +> 1 3 5 6 7 8 9 0 + +clear all: +> 0 +done + +TBC at end with clipping: ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcd! + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0082-HTS.in b/xterm.js/fixtures/escape_sequence_files/t0082-HTS.in new file mode 100644 index 0000000..2bd62d4 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0082-HTS.in @@ -0,0 +1,8 @@ + 1 2 3 4 +abcdeHFghijklmnopqrstuvHWxyz + H 1 2 W 3 4 + +HTS at end: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdeHfgh + H 1 2 W 3 4 5 6 7 8 9 a b + +HTS at end with clipping: ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdeHMD! diff --git a/xterm.js/fixtures/escape_sequence_files/t0082-HTS.text b/xterm.js/fixtures/escape_sequence_files/t0082-HTS.text new file mode 100644 index 0000000..ecf66a5 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0082-HTS.text @@ -0,0 +1,25 @@ + 1 2 3 4 +abcdeFghijklmnopqrstuvWxyz + H 1 2 W 3 4 + +HTS at end: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcde +fgh + H 1 2 W 3 4 5 6 7 8 9 a +b + +HTS at end with clipping: ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcd! + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0083-CHT.in b/xterm.js/fixtures/escape_sequence_files/t0083-CHT.in new file mode 100644 index 0000000..838325d --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0083-CHT.in @@ -0,0 +1,18 @@ +abcdefghijkl +x +12 + 3 + +CHT before EOL: +no tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh@ +tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh@ +tab (2):abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefg@ + +CHT at EOL: +no tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi@ +tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi@ +with clipping: 4567890abcdefghiMD@ + +aeg +e h +x diff --git a/xterm.js/fixtures/escape_sequence_files/t0083-CHT.text b/xterm.js/fixtures/escape_sequence_files/t0083-CHT.text new file mode 100644 index 0000000..071ed63 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0083-CHT.text @@ -0,0 +1,25 @@ +a b c d e f g h i j k +l + x +1 3 2 + + +CHT before EOL: +no tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh@ +tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefgh@ +tab (2):abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefg @ + +CHT at EOL: +no tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi +@ +tab: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890abcdefghi +@ +with clipping: 4567890abcdefgh@ + +a e g + e h + x + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0084-CBT.in b/xterm.js/fixtures/escape_sequence_files/t0084-CBT.in new file mode 100644 index 0000000..a7dd5b1 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0084-CBT.in @@ -0,0 +1,16 @@ +a b c d e f g h i j k + <Iihfa +a + +default tab stops: +near end: abcdefg! +at end: abcdefgh! +at end (2): abcdefgh! +at end with clipping: abcdefghMD! +at end with clipping (2): abcdefghMD! + +set tab stop at column 80: Hv +at end: abcdefgh! +at end (2): abcdefgh! +at end with clipping: abcdefghMD! +at end with clipping (2): abcdefghMD! diff --git a/xterm.js/fixtures/escape_sequence_files/t0084-CBT.text b/xterm.js/fixtures/escape_sequence_files/t0084-CBT.text new file mode 100644 index 0000000..2fb8765 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0084-CBT.text @@ -0,0 +1,25 @@ +a b c d e f g h i j k +a f h i < +a + +default tab stops: +near end: !bcdefg +at end: abcdefgh +! +at end (2): abcdefgh +! +at end with clipping: !bcdefgh +at end with clipping (2): ! abcdefgh + +set tab stop at column 80: v +at end: abcdefgh +! +at end (2): abcdefgh +! +at end with clipping: !bcdefgh +at end with clipping (2): ! abcdefgh + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0084-CBT.text-xterm b/xterm.js/fixtures/escape_sequence_files/t0084-CBT.text-xterm new file mode 100644 index 0000000..7a2adc7 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0084-CBT.text-xterm @@ -0,0 +1,20 @@ +a b c d e f g h i j k +a f h i < +a + +default tab stops: +near end: !bcdefg +at end: abcdefgh +! +at end (2): abcdefgh +! +at end with clipping: !bcdefgh +at end with clipping (2): ! abcdefgh + +set tab stop at column 80: v +at end: abcdefgh +! +at end (2): abcdefgh +! +at end with clipping: !bcdefgh +at end with clipping (2): ! abcdefgh diff --git a/xterm.js/fixtures/escape_sequence_files/t0090-alt_screen.in b/xterm.js/fixtures/escape_sequence_files/t0090-alt_screen.in new file mode 100644 index 0000000..bf1eeaf --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0090-alt_screen.in @@ -0,0 +1,55 @@ +a[?47h +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y[?47lz +A[?47h +B +C +D +E +F +G +H +I +J +K +L +M +N +O +P +Q +R +S +T +U +V +W +X +Y[?47lZ + --->[?47hhello[?47l<-- + + --->[?47h[?47l<--- + +fin diff --git a/xterm.js/fixtures/escape_sequence_files/t0090-alt_screen.text b/xterm.js/fixtures/escape_sequence_files/t0090-alt_screen.text new file mode 100644 index 0000000..7ac0135 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0090-alt_screen.text @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + z +AZ + <-- ---> + + ---> +<--- + +fin + diff --git a/xterm.js/fixtures/escape_sequence_files/t0091-alt_screen_ED3.in b/xterm.js/fixtures/escape_sequence_files/t0091-alt_screen_ED3.in new file mode 100644 index 0000000..40957e8 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0091-alt_screen_ED3.in @@ -0,0 +1,46 @@ +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +[?47h +one +two +three +four +five +six + +[?47l +11 diff --git a/xterm.js/fixtures/escape_sequence_files/t0091-alt_screen_ED3.text b/xterm.js/fixtures/escape_sequence_files/t0091-alt_screen_ED3.text new file mode 100644 index 0000000..4a326a4 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0091-alt_screen_ED3.text @@ -0,0 +1,25 @@ + n + o + p + q + r + s + t + u + v + w + x + y + z + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + + 11 diff --git a/xterm.js/fixtures/escape_sequence_files/t0092-alt_screen_DECSC.in b/xterm.js/fixtures/escape_sequence_files/t0092-alt_screen_DECSC.in new file mode 100644 index 0000000..3022a93 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0092-alt_screen_DECSC.in @@ -0,0 +1,15 @@ +a + b7 + c[?47h + + >7 + + xxxxxxx8[?47l!8< + + + + + + + +The end. diff --git a/xterm.js/fixtures/escape_sequence_files/t0092-alt_screen_DECSC.text b/xterm.js/fixtures/escape_sequence_files/t0092-alt_screen_DECSC.text new file mode 100644 index 0000000..bab1503 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0092-alt_screen_DECSC.text @@ -0,0 +1,25 @@ +a + b< + c + + ! + + + + +The end. + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0100-IRM.in b/xterm.js/fixtures/escape_sequence_files/t0100-IRM.in new file mode 100644 index 0000000..5046f18 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0100-IRM.in @@ -0,0 +1,13 @@ +-------- insert single '!' --------------------------------------------abcdefghi +jklmnop! + + +-------- insert 0-9, with wraparound ----------------------------------abcdefghi +jklmnop0123456789 + +-------- repeat 3 '!' -------------------------------------------------abcdefghi +jklmnop! + + +-------- repeat 10 '!', with wraparound -------------------------------abcdefghi +jklmnop! diff --git a/xterm.js/fixtures/escape_sequence_files/t0100-IRM.text b/xterm.js/fixtures/escape_sequence_files/t0100-IRM.text new file mode 100644 index 0000000..f4f3eea --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0100-IRM.text @@ -0,0 +1,25 @@ +-------- insert single '!' --------------------------------------------abc!defgh +jklmnop + +-------- insert 0-9, with wraparound ----------------------------------abc012345 +6789jklmnop + +-------- repeat 3 '!' -------------------------------------------------abc!!!def +jklmnop + +-------- repeat 10 '!', with wraparound -------------------------------abc!!!!!! +!!!!jklmnop + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0101-NLM.in b/xterm.js/fixtures/escape_sequence_files/t0101-NLM.in new file mode 100644 index 0000000..554a0f3 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0101-NLM.in @@ -0,0 +1,10 @@ +a +b +c +d +e +f g h +i j k +l +m +n o p diff --git a/xterm.js/fixtures/escape_sequence_files/t0101-NLM.text b/xterm.js/fixtures/escape_sequence_files/t0101-NLM.text new file mode 100644 index 0000000..47f883f --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0101-NLM.text @@ -0,0 +1,25 @@ +a +b +c +d +e +f +g +h +k +l +m +n + o + p + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0102-DECAWM.in b/xterm.js/fixtures/escape_sequence_files/t0102-DECAWM.in new file mode 100644 index 0000000..c615659 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0102-DECAWM.in @@ -0,0 +1,4 @@ +-------- default: wraparound ----------------------------------------------abcdefgh[?7h +-------- set: wraparound ----------------------------------------------abcdefgh[?7l +-------- unset: no wraparound -------------------------------------------abcdefgh + this should be immediately below "no wraparound"[?7h diff --git a/xterm.js/fixtures/escape_sequence_files/t0102-DECAWM.text b/xterm.js/fixtures/escape_sequence_files/t0102-DECAWM.text new file mode 100644 index 0000000..c1f22de --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0102-DECAWM.text @@ -0,0 +1,25 @@ +-------- default: wraparound ----------------------------------------------abcd +efgh +-------- set: wraparound ----------------------------------------------abcd +efgh +-------- unset: no wraparound -------------------------------------------abcd + this should be immediately below "no wraparound" + + + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0103-reverse_wrap.in b/xterm.js/fixtures/escape_sequence_files/t0103-reverse_wrap.in new file mode 100644 index 0000000..092462e --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0103-reverse_wrap.in @@ -0,0 +1,6 @@ +[?45ha +bA + +c-B + +dC!the endreally![?45l diff --git a/xterm.js/fixtures/escape_sequence_files/t0103-reverse_wrap.text b/xterm.js/fixtures/escape_sequence_files/t0103-reverse_wrap.text new file mode 100644 index 0000000..da830d5 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0103-reverse_wrap.text @@ -0,0 +1,25 @@ +c C +! + + + + + + + + + + + + + + + + + + + + + the end +really! + diff --git a/xterm.js/fixtures/escape_sequence_files/t0200-SGR.html b/xterm.js/fixtures/escape_sequence_files/t0200-SGR.html new file mode 100644 index 0000000..fa270a0 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0200-SGR.html @@ -0,0 +1,35 @@ +
+Implemented non-color attributes:
+
+ 1: This is bold.
+
+ 3: This is italic.
+
+ 4: This is underlined.
+
+ 5: This is slowly blinking.
+
+ 6: This is rapidly blinking.
+
+ 7: This is inverse.
+
+ 8: This is hidden.
+
+ 9: This is struck out.
+
+21: This is double underlined.
+
+53: This is overlined.
+
+
+
+Unimplemented non-color attributes:
+
+ 2: weight:feint
+
+20: style:fraktur
+
+51: frame:box
+
+52: frame:circle
+
diff --git a/xterm.js/fixtures/escape_sequence_files/t0200-SGR.in_ b/xterm.js/fixtures/escape_sequence_files/t0200-SGR.in_ new file mode 100644 index 0000000..3b37c93 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0200-SGR.in_ @@ -0,0 +1,33 @@ +Implemented non-color attributes: + + 1: This is bold. + + 3: This is italic. + + 4: This is underlined. + + 5: This is slowly blinking. + + 6: This is rapidly blinking. + + 7: This is inverse. + + 8: This is hidden. + + 9: This is struck out. + +21: This is double underlined. + +53: This is overlined. + + + +Unimplemented non-color attributes: + + 2: weight:feint + +20: style:fraktur + +51: frame:box + +52: frame:circle diff --git a/xterm.js/fixtures/escape_sequence_files/t0220-SGR_inverse.html b/xterm.js/fixtures/escape_sequence_files/t0220-SGR_inverse.html new file mode 100644 index 0000000..7218bf4 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0220-SGR_inverse.html @@ -0,0 +1,6 @@ +
+This is inverse text with default fg and bg.
+This is inverse text with red fg and default bg.
+This is inverse text with default fg and red bg.
+This is inverse text with green fg and red bg.
+
diff --git a/xterm.js/fixtures/escape_sequence_files/t0220-SGR_inverse.in_ b/xterm.js/fixtures/escape_sequence_files/t0220-SGR_inverse.in_ new file mode 100644 index 0000000..e7e63f9 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0220-SGR_inverse.in_ @@ -0,0 +1,4 @@ +This is inverse text with default fg and bg. +This is inverse text with red fg and default bg. +This is inverse text with default fg and red bg. +This is inverse text with green fg and red bg. diff --git a/xterm.js/fixtures/escape_sequence_files/t0500-bash_long_line.in b/xterm.js/fixtures/escape_sequence_files/t0500-bash_long_line.in new file mode 100644 index 0000000..b1e5491 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0500-bash_long_line.in @@ -0,0 +1,7 @@ +Script started on Fri 27 Mar 2009 08:53:29 PM EDT +dircolors: /etc/DIR_COLORS: No such file or directory +]0;mark@mark-desktop:~/vt100-to-htmlmark@mark-desktop:~/vt100-to-html$ bcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRST UVWXYZ1234567890abcdefghijklmnopqrstuvcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuv + +]0;mark@mark-desktop:~/vt100-to-htmlmark@mark-desktop:~/vt100-to-html$ exit + +Script done on Fri 27 Mar 2009 08:53:33 PM EDT diff --git a/xterm.js/fixtures/escape_sequence_files/t0500-bash_long_line.text b/xterm.js/fixtures/escape_sequence_files/t0500-bash_long_line.text new file mode 100644 index 0000000..5c785d0 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0500-bash_long_line.text @@ -0,0 +1,25 @@ +Script started on Fri 27 Mar 2009 08:53:29 PM EDT +dircolors: /etc/DIR_COLORS: No such file or directory +mark@mark-desktop:~/vt100-to-html$ cdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTU +VWXYZ1234567890abcdefghijklmnopqrstuv +mark@mark-desktop:~/vt100-to-html$ exit + +Script done on Fri 27 Mar 2009 08:53:33 PM EDT + + + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0501-bash_ls.in b/xterm.js/fixtures/escape_sequence_files/t0501-bash_ls.in new file mode 100644 index 0000000..9053d8b --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0501-bash_ls.in @@ -0,0 +1,12 @@ +Script started on Sun 17 May 2009 06:20:41 PM EDT +dircolors: /etc/DIR_COLORS: No such file or directory +]0;mark@mark-desktop:~/vt100-to-html/scriptsmark@mark-desktop:~/vt100-to-html/scripts$ ls +bash.script +]0;mark@mark-desktop:~/vt100-to-html/scriptsmark@mark-desktop:~/vt100-to-html/scripts$ ls / +bin dev initrd.img lib64 opt selinux usr +boot etc initrd.img.old lost+found proc srv var +boot2 home lib media root sys vmlinuz +cdrom initrd lib32 mnt sbin tmp vmlinuz.old +]0;mark@mark-desktop:~/vt100-to-html/scriptsmark@mark-desktop:~/vt100-to-html/scripts$ exit + +Script done on Sun 17 May 2009 06:20:52 PM EDT diff --git a/xterm.js/fixtures/escape_sequence_files/t0501-bash_ls.text b/xterm.js/fixtures/escape_sequence_files/t0501-bash_ls.text new file mode 100644 index 0000000..8114fc9 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0501-bash_ls.text @@ -0,0 +1,25 @@ +Script started on Sun 17 May 2009 06:20:41 PM EDT +dircolors: /etc/DIR_COLORS: No such file or directory +mark@mark-desktop:~/vt100-to-html/scripts$ ls +bash.script +mark@mark-desktop:~/vt100-to-html/scripts$ ls / +bin dev initrd.img lib64 opt selinux usr +boot etc initrd.img.old lost+found proc srv var +boot2 home lib media root sys vmlinuz +cdrom initrd lib32 mnt sbin tmp vmlinuz.old +mark@mark-desktop:~/vt100-to-html/scripts$ exit + +Script done on Sun 17 May 2009 06:20:52 PM EDT + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0502-bash_ls_color.in b/xterm.js/fixtures/escape_sequence_files/t0502-bash_ls_color.in new file mode 100644 index 0000000..1f4eda8 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0502-bash_ls_color.in @@ -0,0 +1,10 @@ +Script started on Sun 17 May 2009 06:21:05 PM EDT +dircolors: /etc/DIR_COLORS: No such file or directory +]0;mark@mark-desktop:~/vt100-to-html/scriptsmark@mark-desktop:~/vt100-to-html/scripts$ ls --color=auto / +bin dev initrd.img lib64 opt selinux usr +boot etc initrd.img.old lost+found proc srv var +boot2 home lib media root sys vmlinuz +cdrom initrd lib32 mnt sbin tmp vmlinuz.old +]0;mark@mark-desktop:~/vt100-to-html/scriptsmark@mark-desktop:~/vt100-to-html/scripts$ exit + +Script done on Sun 17 May 2009 06:21:11 PM EDT diff --git a/xterm.js/fixtures/escape_sequence_files/t0502-bash_ls_color.text b/xterm.js/fixtures/escape_sequence_files/t0502-bash_ls_color.text new file mode 100644 index 0000000..1892eea --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0502-bash_ls_color.text @@ -0,0 +1,25 @@ +Script started on Sun 17 May 2009 06:21:05 PM EDT +dircolors: /etc/DIR_COLORS: No such file or directory +mark@mark-desktop:~/vt100-to-html/scripts$ ls --color=auto / +bin dev initrd.img lib64 opt selinux usr +boot etc initrd.img.old lost+found proc srv var +boot2 home lib media root sys vmlinuz +cdrom initrd lib32 mnt sbin tmp vmlinuz.old +mark@mark-desktop:~/vt100-to-html/scripts$ exit + +Script done on Sun 17 May 2009 06:21:11 PM EDT + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0503-zsh_ls_color.in b/xterm.js/fixtures/escape_sequence_files/t0503-zsh_ls_color.in new file mode 100644 index 0000000..aca2d10 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0503-zsh_ls_color.in @@ -0,0 +1,9 @@ +Script started on Sun 17 May 2009 06:21:21 PM EDT +]2;mark-desktop - ~/vt100-to-html/scripts% $ ~/vt100-to-html/scriptslls / +]2;mark-desktop - ls /bin dev initrd.img lib64 opt selinux usr +boot etc initrd.img.old lost+found proc srv var +boot2 home lib media root sys vmlinuz +cdrom initrd lib32 mnt sbin tmp vmlinuz.old +]2;mark-desktop - ~/vt100-to-html/scripts% $ ~/vt100-to-html/scripts + +Script done on Sun 17 May 2009 06:21:27 PM EDT diff --git a/xterm.js/fixtures/escape_sequence_files/t0503-zsh_ls_color.text b/xterm.js/fixtures/escape_sequence_files/t0503-zsh_ls_color.text new file mode 100644 index 0000000..19feb18 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0503-zsh_ls_color.text @@ -0,0 +1,25 @@ +Script started on Sun 17 May 2009 06:21:21 PM EDT +$ ls / ~/vt100-to-html/scripts +bin dev initrd.img lib64 opt selinux usr +boot etc initrd.img.old lost+found proc srv var +boot2 home lib media root sys vmlinuz +cdrom initrd lib32 mnt sbin tmp vmlinuz.old +$ ~/vt100-to-html/scripts + +Script done on Sun 17 May 2009 06:21:27 PM EDT + + + + + + + + + + + + + + + + diff --git a/xterm.js/fixtures/escape_sequence_files/t0504-vim.in b/xterm.js/fixtures/escape_sequence_files/t0504-vim.in new file mode 100644 index 0000000..cb68232 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0504-vim.in @@ -0,0 +1,56 @@ +Script started on Sun 15 Aug 2010 11:53:27 PM EDT +]0;mark-desktop - ~/vt100-to-html/test% $ ~/vt100-to-html/testlls +]0;mark-desktop - lsexpected_text t0016-SU.text t0050-ICH.text +input t0017-SD.in t0051-IL.in +run_all.py t0017-SD.text t0051-IL.text +t0001-all_printable.in t0020-CUF.in t0052-DL.in +t0001-all_printable.text t0020-CUF.text t0052-DL.text +t0002-history.in t0021-CUB.in t0053-DCH.in +t0002-history.text t0021-CUB.text t0053-DCH.text +t0003-line_wrap.in t0022-CUU.in t0054-ECH.in +t0003-line_wrap.text t0022-CUU.text t0054-ECH.text +t0004-LF.in t0023-CUU_scroll.in t0055-EL.in +t0004-LF.text t0023-CUU_scroll.text t0055-EL.text +t0005-CR.in t0024-CUD.in t0056-ED.in +t0005-CR.text t0024-CUD.text t0056-ED.text +t0006-IND.in t0025-CUP.in t0057-ED3.in +t0006-IND.text t0025-CUP.text t0057-ED3.note +t0007-space_at_end.in t0026-CNL.in t0057-ED3.text +t0007-space_at_end.text t0026-CNL.text t0060-DECSC.in +t0008-BS.in t0027-CPL.in t0060-DECSC.text +t0008-BS.text t0027-CPL.text t0061-CSI_s.in +t0009-NEL.in t0030-HPR.in t0061-CSI_s.text +t0009-NEL.text t0030-HPR.text t008x-alt_screen_ED.in +t0010-RI.in t0031-HPB.in t008x-IRM.in +t0010-RI.text t0031-HPB.text t008x-NLM.in +t0011-RI_scroll.in t0032-VPB.in t008x-save_cursor_mode.in +t0011-RI_scroll.text t0032-VPB.text t0500-bash_long_line.in +t0012-VT.in t0033-VPB_scroll.in t0500-bash_long_line.text +t0012-VT.text t0033-VPB_scroll.text t0501-bash_ls.in +t0013-FF.in t0034-VPR.in t0501-bash_ls.text +t0013-FF.text t0034-VPR.text t0502-bash_ls_color.in +t0014-CAN.in t0035-HVP.in t0502-bash_ls_color.text +t0014-CAN.text t0035-HVP.text t0503-zsh_ls_color.in +t0015-SUB.in t0040-REP.in t0503-zsh_ls_color.text +t0015-SUB.text t0040-REP.text typescript +t0016-SU.in t0050-ICH.in +]0;mark-desktop - ~/vt100-to-html/test% $ ~/vt100-to-html/testvvim +]0;mark-desktop - vim[?1000h[?1049h[?1h=[?12;25h[?12l[?25h[>c[?25l~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ [No Name] 0,0-1 AllVIM - Vi IMprovedversion 7.2.267by Bram Moolenaar et al.Vim is open source and freely distributableBecome a registered Vim user!type :help register for information type :q to exit type :help or  for on-line helptype :help version7 for version info]2;[No Name] - VIM]1;[No Name][?12l[?25h[?1000l[?1002hP+q436f\P+q6b75\P+q6b64\P+q6b72\P+q6b6c\P+q2332\P+q2334\P+q2569\P+q2a37\P+q6b31\[?25l-- INSERT --1 [?12l[?25h[?25lT         [+]1,2 ]2;[No Name] + - VIM]1;[No Name][?12l[?25h[?25lTh3 [?12l[?25h[?25lhi4 [?12l[?25h[?25lis5 [?12l[?25h[?25l6 [?12l[?25h[?25l i7 [?12l[?25h[?25lis8 [?12l[?25h[?25l9 [?12l[?25h[?25l a10[?12l[?25h[?25l1 [?12l[?25h[?25l t2 [?12l[?25h[?25lte3 [?12l[?25h[?25les4 [?12l[?25h[?25lst5 [?12l[?25h[?25lt.6 [?12l[?25h[?25l2,1 [?12l[?25h[?25l3,[?12l[?25h[?25lH2 [?12l[?25h[?25lHo3 [?12l[?25h[?25loe4 [?12l[?25h[?25l5 [?12l[?25h[?25l f6 [?12l[?25h[?25lfu7 [?12l[?25h[?25l6 [?12l[?25h[?25l5 [?12l[?25h[?25l4 [?12l[?25h[?25l3 [?12l[?25h[?25lop4 [?12l[?25h[?25lpe5 [?12l[?25h[?25lef6 [?12l[?25h[?25lfu7 [?12l[?25h[?25lul8 [?12l[?25h[?25lll9 [?12l[?25h[?25lly10[?12l[?25h[?25l1 [?12l[?25h[?25l i2 [?12l[?25h[?25lit3 [?12l[?25h[?25l4 [?12l[?25h[?25l w5 [?12l[?25h[?25lwi6 [?12l[?25h[?25lil7 [?12l[?25h[?25lll8 [?12l[?25h[?25l9 [?12l[?25h[?25l w20 [?12l[?25h[?25lwo1 [?12l[?25h[?25lor2 [?12l[?25h[?25lrk3 [?12l[?25h[?25lk.4 [?12l[?25h[?25l4,1 [?12l[?25h[?25l5,[?12l[?25h[?25l6,[?12l[?25h[?25l7,[?12l[?25h[?25l8,[?12l[?25h[?25l9,[?12l[?25h[?25l10,1[?12l[?25h[?25l1,[?12l[?25h[?25l2,[?12l[?25h[?25l3,[?12l[?25h[?25l4,[?12l[?25h[?25l5,[?12l[?25h[?25l6,[?12l[?25h[?25l7,[?12l[?25h[?25l8,[?12l[?25h[?25l9,[?12l[?25h[?25l20,[?12l[?25h[?25l1,[?12l[?25h[?25l2,[?12l[?25h[?25l +3,Bot[?12l[?25h[?25l +4,[?12l[?25h[?25l +5,[?12l[?25h[?25l +6,[?12l[?25h[?25l +7,[?12l[?25h[?25l +8,[?12l[?25h[?25l +9,[?12l[?25h[?25l +30,[?12l[?25h[?25l +1,[?12l[?25h[?25l +2,[?12l[?25h[?25l +3,[?12l[?25h[?25lI2 [?12l[?25h[?25l3 [?12l[?25h[?25l b4 [?12l[?25h[?25lbe5 [?12l[?25h[?25let6 [?12l[?25h[?25l7 [?12l[?25h[?25l i8 [?12l[?25h[?25lit9 [?12l[?25h[?25l10[?12l[?25h[?25l w1 [?12l[?25h[?25lwi2 [?12l[?25h[?25lil3 [?12l[?25h[?25lll4 [?12l[?25h[?25ll.5 [?12l[?25h[?25l4 [?12l[?25h[?25lThis is a test. + +Hopefully it will work.1,1 Top[?12l[?25h[?25lI bet it will. +~ ~ ~ ~ ~ ~ ~ ~ ~ [No Name] [+] 21,0-1 Bot[?12l[?25h[?25l0,[?12l[?25h[?25l19,[?12l[?25h[?25l8,[?12l[?25h[?25l7,[?12l[?25h[?25l6,[?12l[?25h[?25l5,[?12l[?25h[?25l:[?12l[?25hw[?25l[?12l[?25hq[?25l[?12l[?25h [?25lE32: No file name[?12l[?25h[?25l:[?12l[?25hw[?25l[?12l[?25h[?25l [?12l[?25hf[?25l[?12l[?25ho[?25l[?12l[?25ho[?25l[?12l[?25h [?25l"foo" [New] 33L, 85C writtenfoo ]2;foo (~/vt100-to-html/test) - VIM]1;foo[?12l[?25h[?25l:[?12l[?25hq[?25l[?12l[?25h [?25l[?1002l]2;mark-desktop - vim]1;mark-desktop - vim[?1l>[?12l[?25h[?1049l]0;mark-desktop - ~/vt100-to-html/test% $ ~/vt100-to-html/testeecho Yes! +]0;mark-desktop - echo Yes!Yes! +]0;mark-desktop - ~/vt100-to-html/test% $ ~/vt100-to-html/test + +Script done on Sun 15 Aug 2010 11:54:14 PM EDT diff --git a/xterm.js/fixtures/escape_sequence_files/t0504-vim.text b/xterm.js/fixtures/escape_sequence_files/t0504-vim.text new file mode 100644 index 0000000..7c20251 --- /dev/null +++ b/xterm.js/fixtures/escape_sequence_files/t0504-vim.text @@ -0,0 +1,25 @@ +t0005-CR.in t0024-CUD.in t0056-ED.in +t0005-CR.text t0024-CUD.text t0056-ED.text +t0006-IND.in t0025-CUP.in t0057-ED3.in +t0006-IND.text t0025-CUP.text t0057-ED3.note +t0007-space_at_end.in t0026-CNL.in t0057-ED3.text +t0007-space_at_end.text t0026-CNL.text t0060-DECSC.in +t0008-BS.in t0027-CPL.in t0060-DECSC.text +t0008-BS.text t0027-CPL.text t0061-CSI_s.in +t0009-NEL.in t0030-HPR.in t0061-CSI_s.text +t0009-NEL.text t0030-HPR.text t008x-alt_screen_ED.in +t0010-RI.in t0031-HPB.in t008x-IRM.in +t0010-RI.text t0031-HPB.text t008x-NLM.in +t0011-RI_scroll.in t0032-VPB.in t008x-save_cursor_mode.in +t0011-RI_scroll.text t0032-VPB.text t0500-bash_long_line.in +t0012-VT.in t0033-VPB_scroll.in t0500-bash_long_line.text +t0012-VT.text t0033-VPB_scroll.text t0501-bash_ls.in +t0013-FF.in t0034-VPR.in t0501-bash_ls.text +t0013-FF.text t0034-VPR.text t0502-bash_ls_color.in +t0014-CAN.in t0035-HVP.in t0502-bash_ls_color.text +t0014-CAN.text t0035-HVP.text t0503-zsh_ls_color.in +t0015-SUB.in t0040-REP.in t0503-zsh_ls_color.text +t0015-SUB.text t0040-REP.text typescript +t0016-SU.in t0050-ICH.in +$ vim ~/vt100-to-html/test +Script done on Sun 15 Aug 2010 11:54:14 PM EDT ~/vt100-to-html/test diff --git a/xterm.js/fixtures/typings-test/tsconfig.json b/xterm.js/fixtures/typings-test/tsconfig.json new file mode 100644 index 0000000..2dcff2e --- /dev/null +++ b/xterm.js/fixtures/typings-test/tsconfig.json @@ -0,0 +1,9 @@ +{ + "files": [ + "typings-test.ts" + ], + "compilerOptions": { + "module": "commonjs", + "target": "es5" + } +} diff --git a/xterm.js/fixtures/typings-test/typings-test.ts b/xterm.js/fixtures/typings-test/typings-test.ts new file mode 100644 index 0000000..a9653b1 --- /dev/null +++ b/xterm.js/fixtures/typings-test/typings-test.ts @@ -0,0 +1,234 @@ +/** + * @license MIT + */ + +/// + +import { Terminal } from 'xterm'; + +namespace constructor { + { + new Terminal(); + new Terminal({}); + new Terminal({ + cols: 1, + rows: 1 + }); + new Terminal({ + 'cols': 1, + 'cursorBlink': true, + 'cursorStyle': 'block', + 'disableStdin': false, + 'rows': 1, + 'scrollback': 10, + 'tabStopWidth': 2, + }); + } +} + +namespace properties { + { + const t: Terminal = new Terminal(); + const element: HTMLElement = t.element; + const textarea: HTMLTextAreaElement = t.textarea; + } +} + +namespace static_methods { + { + Terminal.applyAddon({}); + Terminal.applyAddon({}); + Terminal.applyAddon({}); + Terminal.applyAddon({}); + Terminal.applyAddon({}); + Terminal.applyAddon({}); + } +} + +namespace methods_core { + { + const t: Terminal = new Terminal(); + t.blur(); + t.focus(); + t.destroy(); + t.clear(); + t.refresh(0, 1); + t.reset(); + t.resize(1, 1); + t.write('foo'); + t.writeln('foo'); + } + { + const t: Terminal = new Terminal(); + // no arg + t.on('blur', () => {}); + t.on('focus', () => {}); + t.on('linefeed', () => {}); + t.on('selection', () => {}); + // args + t.on('data', () => {}); + t.on('data', (data: string) => console.log(data)); + t.on('key', () => {}); + t.on('key', (key: string) => console.log(key, event)); + t.on('key', (key: string, event: KeyboardEvent) => console.log(key, event)); + t.on('keydown', () => {}); + t.on('keydown', (event: KeyboardEvent) => console.log(event)); + t.on('keypress', () => {}); + t.on('keypress', (event: KeyboardEvent) => console.log(event)); + t.on('refresh', () => {}); + t.on('refresh', (data: {start: number, end: number}) => console.log(data)); + t.on('resize', () => {}); + t.on('resize', (data: {cols: number, rows: number}) => console.log(data)); + t.on('scroll', () => {}); + t.on('scroll', (ydisp: number) => console.log(ydisp)); + t.on('title', () => {}); + t.on('title', (title: string) => console.log(title)); + } + { + const t: Terminal = new Terminal(); + // no arg + t.off('blur', () => {}); + t.off('focus', () => {}); + t.off('linefeed', () => {}); + t.off('selection', () => {}); + // args + t.off('data', () => {}); + t.off('data', (data: string) => console.log(data)); + t.off('key', () => {}); + t.off('key', (key: string) => console.log(key, event)); + t.off('key', (key: string, event: KeyboardEvent) => console.log(key, event)); + t.off('keydown', () => {}); + t.off('keydown', (event: KeyboardEvent) => console.log(event)); + t.off('keypress', () => {}); + t.off('keypress', (event: KeyboardEvent) => console.log(event)); + t.off('refresh', () => {}); + t.off('refresh', (data: {element: HTMLElement, start: number, end: number}) => console.log(data)); + t.off('resize', () => {}); + t.off('resize', (data: {terminal: Terminal, cols: number, rows: number}) => console.log(data)); + t.off('scroll', () => {}); + t.off('scroll', (ydisp: number) => console.log(ydisp)); + t.off('title', () => {}); + t.off('title', (title: string) => console.log(title)); + } + { + const t: Terminal = new Terminal(); + const e: HTMLElement = null; + t.open(e); + } + { + const t: Terminal = new Terminal(); + t.attachCustomKeyEventHandler((e: KeyboardEvent) => true); + t.attachCustomKeyEventHandler((e: KeyboardEvent) => false); + } + namespace options { + { + const t: Terminal = new Terminal(); + const r01: string = t.getOption('cursorStyle'); + const r02: string = t.getOption('termName'); + const r03: boolean = t.getOption('cancelEvents'); + const r04: boolean = t.getOption('convertEol'); + const r05: boolean = t.getOption('cursorBlink'); + const r06: boolean = t.getOption('debug'); + const r07: boolean = t.getOption('disableStdin'); + const r08: boolean = t.getOption('popOnBell'); + const r09: boolean = t.getOption('screenKeys'); + const r10: boolean = t.getOption('useFlowControl'); + const r11: boolean = t.getOption('visualBell'); + const r12: string[] = t.getOption('colors'); + const r13: number = t.getOption('cols'); + const r14: number = t.getOption('rows'); + const r15: number = t.getOption('tabStopWidth'); + const r16: number = t.getOption('scrollback'); + const r18: (data: string) => void = t.getOption('handler'); + const r19: string = t.getOption('bellSound'); + const r20: string = t.getOption('bellStyle'); + const r21: boolean = t.getOption('enableBold'); + const r22: number = t.getOption('letterSpacing'); + const r23: boolean = t.getOption('allowTransparency'); + } + { + const t: Terminal = new Terminal(); + t.setOption('cursorStyle', 'bar'); + t.setOption('cursorStyle', 'block'); + t.setOption('cursorStyle', 'underline'); + t.setOption('termName', 'foo'); + t.setOption('cancelEvents', true); + t.setOption('convertEol', true); + t.setOption('cursorBlink', true); + t.setOption('debug', true); + t.setOption('disableStdin', true); + t.setOption('enableBold', true); + t.setOption('popOnBell', true); + t.setOption('screenKeys', true); + t.setOption('useFlowControl', true); + t.setOption('allowTransparency', true); + t.setOption('visualBell', true); + t.setOption('colors', ['a', 'b']); + t.setOption('letterSpacing', 1); + t.setOption('cols', 1); + t.setOption('rows', 1); + t.setOption('tabStopWidth', 1); + t.setOption('scrollback', 1); + t.setOption('handler', (data: string) => console.log(data)); + t.setOption('bellSound', 'foo'); + t.setOption('bellStyle', 'none'); + // t.setOption('bellStyle', 'visual'); + t.setOption('bellStyle', 'sound'); + // t.setOption('bellStyle', 'both'); + t.setOption('fontSize', 1); + t.setOption('lineHeight', 1); + t.setOption('fontFamily', 'foo'); + t.setOption('theme', {background: '#ff0000'}); + } + } + namespace scrolling { + { + const t: Terminal = new Terminal(); + t.scrollLines(-1); + t.scrollLines(1); + t.scrollLines(-1); + t.scrollLines(1); + t.scrollToTop(); + t.scrollToBottom(); + } + } + namespace selection { + { + const t: Terminal = new Terminal(); + const r1: boolean = t.hasSelection(); + const r2: string = t.getSelection(); + t.clearSelection(); + t.selectAll(); + } + } +} + +namespace methods_experimental { + { + const t: Terminal = new Terminal(); + t.registerLinkMatcher(/foo/, () => {}); + t.registerLinkMatcher(new RegExp('foo'), () => {}); + t.registerLinkMatcher(/foo/, () => {}, {}); + t.registerLinkMatcher(/foo/, (event: MouseEvent, uri: string) => { + console.log(event, uri); + return void 0; + }, {}); + t.registerLinkMatcher(/foo/, () => true, {}); + t.registerLinkMatcher(/foo/, () => false, {}); + t.registerLinkMatcher(/foo/, () => true, { + matchIndex: 1 + }); + t.registerLinkMatcher(/foo/, () => true, { + matchIndex: 1, + priority: 1, + validationCallback: (uri: string, callback: (isValid: boolean) => void) => { + console.log(uri, callback); + }, + tooltipCallback: (e: MouseEvent, uri: string) => { + console.log(e, uri); + }, + leaveCallback: () => {} + }); + t.deregisterLinkMatcher(1); + } +} diff --git a/xterm.js/gulpfile.js b/xterm.js/gulpfile.js new file mode 100644 index 0000000..49d67ed --- /dev/null +++ b/xterm.js/gulpfile.js @@ -0,0 +1,213 @@ +/** + * @license MIT + */ + +const browserify = require('browserify'); +const buffer = require('vinyl-buffer'); +const coveralls = require('gulp-coveralls'); +const fs = require('fs-extra'); +const gulp = require('gulp'); +const path = require('path'); +const istanbul = require('gulp-istanbul'); +const merge = require('merge-stream'); +const mocha = require('gulp-mocha'); +const sorcery = require('sorcery'); +const source = require('vinyl-source-stream'); +const sourcemaps = require('gulp-sourcemaps'); +const ts = require('gulp-typescript'); +const util = require('gulp-util'); +const webpack = require('webpack-stream'); + +let buildDir = process.env.BUILD_DIR || 'build'; +let tsProject = ts.createProject('tsconfig.json'); +let srcDir = tsProject.config.compilerOptions.rootDir; +let outDir = tsProject.config.compilerOptions.outDir; + +// Under some environments like TravisCI, this comes out at absolute which can +// break the build. This ensures that the outDir is absolute. +if (path.normalize(outDir).indexOf(__dirname) !== 0) { + outDir = `${__dirname}/${path.normalize(outDir)}`; +} + +/** + * Compile TypeScript sources to JavaScript files and create a source map file for each TypeScript + * file compiled. + */ +gulp.task('tsc', function () { + // Remove the ${outDir}/ directory to prevent confusion if files were deleted in ${srcDir}/ + fs.emptyDirSync(`${outDir}`); + + // Build all TypeScript files (including tests) to ${outDir}/, based on the configuration defined in + // `tsconfig.json`. + let tsResult = tsProject.src().pipe(sourcemaps.init()).pipe(tsProject()); + let tsc = merge( + tsResult.js.pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''})).pipe(gulp.dest(outDir)), + tsResult.dts.pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''})).pipe(gulp.dest(outDir)) + ); + + let addons = ['attach', 'fit', 'fullscreen', 'search', 'terminado', 'winptyCompat', 'zmodem']; + let addonStreams = addons.map(function(addon) { + fs.emptyDirSync(`${outDir}/addons/${addon}`); + + let tsProjectAddon = ts.createProject(`./src/addons/${addon}/tsconfig.json`); + let tsResultAddon = tsProjectAddon.src().pipe(sourcemaps.init()).pipe(tsProjectAddon()); + let tscAddon = tsResultAddon.js + .pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: ''})) + .pipe(gulp.dest(`${outDir}/addons/${addon}`)); + + return tscAddon; + }); + + // Copy all addons from ${srcDir}/ to ${outDir}/ + let copyAddons = gulp.src([ + `${srcDir}/addons/**/**` + ]).pipe(gulp.dest(`${outDir}/addons`)); + + // Copy stylesheets from ${srcDir}/ to ${outDir}/ + let copyStylesheets = gulp.src(`${srcDir}/**/*.css`).pipe(gulp.dest(outDir)); + + // Join all streams into a single array + let streams = [tsc].concat(addonStreams).concat([copyAddons, copyStylesheets]); + + return merge.apply(this, streams); +}); + +/** + * Bundle JavaScript files produced by the `tsc` task, into a single file named `xterm.js` with + * Browserify. + */ +gulp.task('browserify', ['tsc'], function() { + // Ensure that the build directory exists + fs.ensureDirSync(buildDir); + + let browserifyOptions = { + basedir: buildDir, + debug: true, + entries: [`${outDir}/xterm.js`], + standalone: 'Terminal', + cache: {}, + packageCache: {} + }; + let bundleStream = browserify(browserifyOptions) + .bundle() + .pipe(source('xterm.js')) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true, sourceRoot: '..'})) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(buildDir)); + + // Copy stylesheets from ${outDir}/ to ${buildDir}/ + let copyStylesheets = gulp.src(`${outDir}/**/*.css`).pipe(gulp.dest(buildDir)); + + return merge(bundleStream, copyStylesheets); +}); + +gulp.task('browserify-addons', ['tsc'], function() { + let searchOptions = { + basedir: `${buildDir}/addons/search`, + debug: true, + entries: [`${outDir}/addons/search/search.js`], + cache: {}, + packageCache: {} + }; + let searchBundle = browserify(searchOptions) + .external(path.join(outDir, 'Terminal.js')) + .bundle() + .pipe(source('./addons/search/search.js')) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true, sourceRoot: ''})) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(buildDir)); + + let winptyCompatOptions = { + basedir: `${buildDir}/addons/winptyCompat`, + debug: true, + entries: [`${outDir}/addons/winptyCompat/winptyCompat.js`], + cache: {}, + packageCache: {} + }; + let winptyCompatBundle = browserify(winptyCompatOptions) + .external(path.join(outDir, 'Terminal.js')) + .bundle() + .pipe(source('./addons/winptyCompat/winptyCompat.js')) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true, sourceRoot: ''})) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest(buildDir)); + + // Copy all add-ons from outDir to buildDir + let copyAddons = gulp.src([ + // Copy JS addons + `${outDir}/addons/**/*` + ]).pipe(gulp.dest(`${buildDir}/addons`)); + + return merge(searchBundle, winptyCompatBundle, copyAddons); +}); + +gulp.task('instrument-test', function () { + return gulp.src([`${outDir}/**/*.js`]) + // Covering files + .pipe(istanbul()) + // Force `require` to return covered files + .pipe(istanbul.hookRequire()); +}); + +gulp.task('mocha', ['instrument-test'], function () { + return gulp.src([ + `${outDir}/*test.js`, + `${outDir}/**/*test.js`, + `${outDir}/*integration.js`, + `${outDir}/**/*integration.js` + ], {read: false}) + .pipe(mocha()) + .once('error', () => process.exit(1)) + .pipe(istanbul.writeReports()); +}); + +/** + * Run single test file by file name(without file extension). Example of the command: + * gulp mocha-test --test InputHandler.test + */ +gulp.task('mocha-test', ['instrument-test'], function () { + let testName = util.env.test; + util.log("Run test by Name: " + testName); + return gulp.src([`${outDir}/${testName}.js`, `${outDir}/**/${testName}.js`], {read: false}) + .pipe(mocha()) + .once('error', () => process.exit(1)) + .pipe(istanbul.writeReports()); +}); + +/** + * Use `sorcery` to resolve the source map chain and point back to the TypeScript files. + * (Without this task the source maps produced for the JavaScript bundle points into the + * compiled JavaScript files in ${outDir}/). + */ +gulp.task('sorcery', ['browserify'], function () { + let chain = sorcery.loadSync(`${buildDir}/xterm.js`); + chain.apply(); + chain.writeSync(); +}); + +gulp.task('sorcery-addons', ['browserify-addons'], function () { + var chain = sorcery.loadSync(`${buildDir}/addons/search/search.js`); + chain.apply(); + chain.writeSync(); +}); + +gulp.task('webpack', ['build'], function() { + return gulp.src('demo/main.js') + .pipe(webpack(require('./webpack.config.js'))) + .pipe(gulp.dest('demo/dist/')); +}); + +/** + * Submit coverage results to coveralls.io + */ +gulp.task('coveralls', function () { + gulp.src('coverage/**/lcov.info') + .pipe(coveralls()); +}); + +gulp.task('build', ['sorcery', 'sorcery-addons']); +gulp.task('test', ['mocha']); +gulp.task('default', ['build']); diff --git a/xterm.js/jsdoc.json b/xterm.js/jsdoc.json new file mode 100644 index 0000000..cd864c8 --- /dev/null +++ b/xterm.js/jsdoc.json @@ -0,0 +1,26 @@ +{ + "source": { + "include": [ + "src/" + ], + "exclude": [ + "src/test/" + ], + "excludePattern": "src/.+\\.test\\.(js|ts)$" + }, + "opts": { + "readme": "README.md", + "template": "node_modules/docdash", + "encoding": "utf8", + "destination": "docs/", + "recurse": true, + "verbose": true + }, + "plugins": [ + "plugins/markdown" + ], + "templates": { + "cleverLinks": false, + "monospaceLinks": false + } +} diff --git a/xterm.js/logo-full.png b/xterm.js/logo-full.png new file mode 100644 index 0000000..53e0827 Binary files /dev/null and b/xterm.js/logo-full.png differ diff --git a/xterm.js/package-lock.json b/xterm.js/package-lock.json new file mode 100644 index 0000000..108fe23 --- /dev/null +++ b/xterm.js/package-lock.json @@ -0,0 +1,15284 @@ +{ + "name": "xterm", + "version": "3.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/chai": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-3.5.2.tgz", + "integrity": "sha1-wRzSgX06QBt7oPWkIPNcVhObHB4=", + "dev": true + }, + "@types/jsdom": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-11.0.1.tgz", + "integrity": "sha512-7C2fXDVHdW+E9JPh++CabVkUbcmI+aI9CYUY4kzPn3UUgnOEk/6vsnBnGv0hs9JHR7mc3+6VUSLdm7SHdg4/lg==", + "dev": true, + "requires": { + "@types/node": "6.0.79", + "@types/tough-cookie": "2.3.0", + "parse5": "3.0.2" + }, + "dependencies": { + "parse5": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.2.tgz", + "integrity": "sha1-Be/1fw70V3+xRKefi5qWemzERRA=", + "dev": true, + "requires": { + "@types/node": "6.0.79" + } + } + } + }, + "@types/mocha": { + "version": "2.2.41", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.41.tgz", + "integrity": "sha1-4nzwgXFT658nE7LT9saPHhw8pgg=", + "dev": true + }, + "@types/node": { + "version": "6.0.79", + "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.79.tgz", + "integrity": "sha512-7F3/P6MkTPA0QxOstRqfcnoReCUy5V/QG92cyBoZSPnqdX44L8TtNELSVfN56gAttm3YWj9cEi8FRIPVq0WmeQ==", + "dev": true + }, + "@types/text-encoding": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/text-encoding/-/text-encoding-0.0.32.tgz", + "integrity": "sha512-kQ79aFmYcD/DR3QKo6wXyvNrKi7PunY0KYTBUhHjHl0SXwWuLRl9Leh73YtnsSJMBi9qSiK+fxWhdJNQPbhc9A==", + "dev": true + }, + "@types/tough-cookie": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.0.tgz", + "integrity": "sha512-bJgf+gJF+zohYkhOOdY7cXVKa0jMZGICqIcdPRb1SFyPHI4sKau0tXTRLmT2T4S5bjx6cY9AuoMkB5v+TIL4wA==", + "dev": true + }, + "JSONStream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", + "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", + "dev": true, + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + }, + "abab": { + "version": "https://registry.npmjs.org/abab/-/abab-1.0.3.tgz", + "integrity": "sha1-uB3l9ydOxOdW15fNg08wNkJyTl0=", + "dev": true + }, + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + }, + "acorn-dynamic-import": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", + "dev": true, + "requires": { + "acorn": "4.0.13" + } + }, + "acorn-globals": { + "version": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", + "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=", + "dev": true, + "requires": { + "acorn": "https://registry.npmjs.org/acorn/-/acorn-4.0.11.tgz" + }, + "dependencies": { + "acorn": { + "version": "https://registry.npmjs.org/acorn/-/acorn-4.0.11.tgz", + "integrity": "sha1-7c2jvZN+dVZBDULtWGD2c5nHlMA=", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-equal": { + "version": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, + "array-slice": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.0.0.tgz", + "integrity": "sha1-5zA08A3MH0CHYAj9IP6ud71LfC8=", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "asn1": { + "version": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "asn1.js": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz", + "integrity": "sha1-SLokC0WpKA6UdImQull9IWYX/UA=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "astw": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", + "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", + "dev": true, + "requires": { + "acorn": "4.0.13" + } + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "asynckit": { + "version": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "bn.js": { + "version": "4.11.7", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.7.tgz", + "integrity": "sha512-LxFiV5mefv0ley0SzqkOPR1bC4EbpPx8LkOz5vMe/Yi15t5hzwgO/G+tc7wOtL4PZTYjwHu8JnEiSLumuSjSfA==", + "dev": true + }, + "boom": { + "version": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-pack": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.2.tgz", + "integrity": "sha1-+GzWzvT1MAyOY+B6TVEvZfv/RTE=", + "dev": true, + "requires": { + "JSONStream": "1.3.1", + "combine-source-map": "0.7.2", + "defined": "1.0.0", + "through2": "2.0.3", + "umd": "3.0.1" + } + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserify": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-13.3.0.tgz", + "integrity": "sha1-tanJAgJD8McORnW+yCI7xifkFc4=", + "dev": true, + "requires": { + "JSONStream": "1.3.1", + "assert": "1.4.1", + "browser-pack": "6.0.2", + "browser-resolve": "1.11.2", + "browserify-zlib": "0.1.4", + "buffer": "4.9.1", + "cached-path-relative": "1.0.1", + "concat-stream": "1.5.2", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.11.1", + "defined": "1.0.0", + "deps-sort": "2.0.0", + "domain-browser": "1.1.7", + "duplexer2": "0.1.4", + "events": "1.1.1", + "glob": "7.1.2", + "has": "1.0.1", + "htmlescape": "1.1.1", + "https-browserify": "0.0.1", + "inherits": "2.0.3", + "insert-module-globals": "7.0.1", + "labeled-stream-splicer": "2.0.0", + "module-deps": "4.1.1", + "os-browserify": "0.1.2", + "parents": "1.0.1", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "read-only-stream": "2.0.0", + "readable-stream": "2.3.3", + "resolve": "1.4.0", + "shasum": "1.0.2", + "shell-quote": "1.6.1", + "stream-browserify": "2.0.1", + "stream-http": "2.7.2", + "string_decoder": "0.10.31", + "subarg": "1.0.0", + "syntax-error": "1.3.0", + "through2": "2.0.3", + "timers-browserify": "1.4.2", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4", + "xtend": "4.0.1" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + }, + "dependencies": { + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "browserify-aes": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.6.tgz", + "integrity": "sha1-Xncl297x/Vkw1OurSFZ85FHEigo=", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, + "requires": { + "browserify-aes": "1.0.6", + "browserify-des": "1.0.0", + "evp_bytestokey": "1.0.0" + } + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "randombytes": "2.0.5" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.0" + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "0.2.9" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8", + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "cached-path-relative": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", + "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "caseless": { + "version": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chai": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "dev": true, + "requires": { + "assertion-error": "1.0.2", + "deep-eql": "0.1.3", + "type-detect": "1.0.0" + }, + "dependencies": { + "assertion-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", + "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", + "dev": true + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dev": true, + "requires": { + "type-detect": "0.1.1" + }, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "dev": true + } + } + }, + "type-detect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", + "dev": true + } + } + }, + "chalk": { + "version": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "escape-string-regexp": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "has-ansi": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "supports-color": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.1.3", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "cloneable-readable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", + "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "process-nextick-args": "1.0.7", + "through2": "2.0.3" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "combine-source-map": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", + "integrity": "sha1-CHAxKFazB6h8xKxIbzqaYq7MwJ4=", + "dev": true, + "requires": { + "convert-source-map": "1.1.3", + "inline-source-map": "0.6.2", + "lodash.memoize": "3.0.4", + "source-map": "0.5.6" + } + }, + "combined-stream": { + "version": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + } + } + }, + "concat-with-sourcemaps": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz", + "integrity": "sha1-9Vs74q60dgGxCi1SWcz7cP0vHdY=", + "dev": true, + "requires": { + "source-map": "0.5.6" + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-type-parser": { + "version": "https://registry.npmjs.org/content-type-parser/-/content-type-parser-1.0.1.tgz", + "integrity": "sha1-w+VpiMU8ZRJ/tG1AMqOpACRv3JQ=", + "dev": true + }, + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + }, + "copy-props": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-1.6.0.tgz", + "integrity": "sha1-8DJLvumXcRAeezraES8xPDk9uO0=", + "dev": true, + "requires": { + "each-props": "1.3.0", + "is-plain-object": "2.0.3" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "crc-32": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.1.1.tgz", + "integrity": "sha1-XXOdXkxuNSrYME1zIj1IP+Va240=", + "dev": true, + "requires": { + "exit-on-epipe": "1.0.1", + "printj": "1.1.0" + } + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.8" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.8" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "cross-spawn-async": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", + "integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "which": "1.2.14" + }, + "dependencies": { + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "which": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + } + } + }, + "cryptiles": { + "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" + } + }, + "crypto-browserify": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz", + "integrity": "sha512-Na7ZlwCOqoaW5RwUK1WpXws2kv8mNhWdTlzob0UXulk6G9BDbyiJaGTYBIX61Ozn9l1EPPJpICZb4DaOpT9NlQ==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.0", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.0", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "diffie-hellman": "5.0.2", + "inherits": "2.0.3", + "pbkdf2": "3.0.12", + "public-encrypt": "4.0.0", + "randombytes": "2.0.5" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + }, + "cssom": { + "version": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz", + "integrity": "sha1-uANhcMefB6kP8vFuIihAJ6JDhIs=", + "dev": true + }, + "cssstyle": { + "version": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", + "integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=", + "dev": true, + "requires": { + "cssom": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz" + } + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.37" + } + }, + "dashdash": { + "version": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + }, + "dependencies": { + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", + "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-is": { + "version": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "delayed-stream": { + "version": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "deps-sort": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "dev": true, + "requires": { + "JSONStream": "1.3.1", + "shasum": "1.0.2", + "subarg": "1.0.0", + "through2": "2.0.3" + } + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "detective": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.5.0.tgz", + "integrity": "sha1-blqMaybmx6JUsca210kNmOyR7dE=", + "dev": true, + "requires": { + "acorn": "4.0.13", + "defined": "1.0.0" + } + }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "miller-rabin": "4.0.0", + "randombytes": "2.0.5" + } + }, + "docdash": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/docdash/-/docdash-0.4.0.tgz", + "integrity": "sha1-BcOlDYMYmYFpnuDAdtOjlQ237AA=", + "dev": true + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "each-props": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.0.tgz", + "integrity": "sha1-ftgDHJJ2iK7bSoluuRSFtEh7kOo=", + "dev": true, + "requires": { + "is-plain-object": "2.0.3", + "object-assign": "4.1.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "ecc-jsbn": { + "version": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" + } + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "enhanced-resolve": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "object-assign": "4.1.1", + "tapable": "0.2.8" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "errno": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", + "integrity": "sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw==", + "dev": true, + "requires": { + "prr": "1.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es5-ext": { + "version": "0.10.37", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", + "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escape-string-regexp": { + "version": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "estraverse": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "esutils": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "optionator": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "source-map": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz" + }, + "dependencies": { + "source-map": { + "version": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" + } + } + } + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "esprima": { + "version": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "estraverse": { + "version": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "esutils": { + "version": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37" + } + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.0.tgz", + "integrity": "sha1-SXtmrZ/vZc18CKYYCCS6FHa2blM=", + "dev": true, + "requires": { + "create-hash": "1.1.3" + } + }, + "execa": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.4.0.tgz", + "integrity": "sha1-TrZGejaglfq7KXD/nV4/t7zm68M=", + "dev": true, + "requires": { + "cross-spawn-async": "2.2.5", + "is-stream": "1.1.0", + "npm-run-path": "1.0.0", + "object-assign": "4.1.1", + "path-key": "1.0.0", + "strip-eof": "1.0.0" + }, + "dependencies": { + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "express": { + "version": "4.13.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.13.4.tgz", + "integrity": "sha1-PAt288d1kMg0VzkGHsC9O6Bn7CQ=", + "dev": true, + "requires": { + "accepts": "1.2.13", + "array-flatten": "1.1.1", + "content-disposition": "0.5.1", + "content-type": "1.0.2", + "cookie": "0.1.5", + "cookie-signature": "1.0.6", + "debug": "2.2.0", + "depd": "1.1.0", + "escape-html": "1.0.3", + "etag": "1.7.0", + "finalhandler": "0.4.1", + "fresh": "0.3.0", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.1", + "path-to-regexp": "0.1.7", + "proxy-addr": "1.0.10", + "qs": "4.0.0", + "range-parser": "1.0.3", + "send": "0.13.1", + "serve-static": "1.10.3", + "type-is": "1.6.15", + "utils-merge": "1.0.0", + "vary": "1.0.1" + }, + "dependencies": { + "accepts": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", + "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", + "dev": true, + "requires": { + "mime-types": "2.1.15", + "negotiator": "0.5.3" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "content-disposition": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz", + "integrity": "sha1-h0dsamfI2qh+Muh2Ft+IO6f7Bxs=", + "dev": true + }, + "content-type": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", + "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=", + "dev": true + }, + "cookie": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.5.tgz", + "integrity": "sha1-armUiksa4hlSzSWIUwpHItQETXw=", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "depd": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", + "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "etag": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", + "dev": true + }, + "finalhandler": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.1.tgz", + "integrity": "sha1-haF8bFmpRxfSYtYSMNSw6+PUoU0=", + "dev": true, + "requires": { + "debug": "2.2.0", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "unpipe": "1.0.0" + } + }, + "forwarded": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", + "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M=", + "dev": true + }, + "fresh": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", + "dev": true + }, + "http-errors": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "statuses": "1.2.1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ipaddr.js": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.0.5.tgz", + "integrity": "sha1-X6eM8wG4JceKvDBC2BJyMEnqI8c=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", + "dev": true + }, + "mime-db": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", + "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=", + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", + "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "negotiator": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", + "integrity": "sha1-Jp1cR2gQ7JLtvntsLygxY4T5p+g=", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", + "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "proxy-addr": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.10.tgz", + "integrity": "sha1-DUCoL4Afw1VWfS7LZe/j8HfxIcU=", + "dev": true, + "requires": { + "forwarded": "0.1.0", + "ipaddr.js": "1.0.5" + } + }, + "qs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", + "integrity": "sha1-wx2bdOwn33XlQ6hseHKO2NRiNgc=", + "dev": true + }, + "range-parser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", + "integrity": "sha1-aHKCNTXGkuLCoBA4Jq/YLC4P8XU=", + "dev": true + }, + "send": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.13.1.tgz", + "integrity": "sha1-ow1fTILIqbrprQCh2bG9vm8Zntc=", + "dev": true, + "requires": { + "debug": "2.2.0", + "depd": "1.1.0", + "destroy": "1.0.4", + "escape-html": "1.0.3", + "etag": "1.7.0", + "fresh": "0.3.0", + "http-errors": "1.3.1", + "mime": "1.3.4", + "ms": "0.7.1", + "on-finished": "2.3.0", + "range-parser": "1.0.3", + "statuses": "1.2.1" + } + }, + "serve-static": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", + "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", + "dev": true, + "requires": { + "escape-html": "1.0.3", + "parseurl": "1.3.1", + "send": "0.13.2" + }, + "dependencies": { + "send": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", + "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", + "dev": true, + "requires": { + "debug": "2.2.0", + "depd": "1.1.0", + "destroy": "1.0.4", + "escape-html": "1.0.3", + "etag": "1.7.0", + "fresh": "0.3.0", + "http-errors": "1.3.1", + "mime": "1.3.4", + "ms": "0.7.1", + "on-finished": "2.3.0", + "range-parser": "1.0.3", + "statuses": "1.2.1" + } + } + } + }, + "statuses": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", + "integrity": "sha1-3e1FzBglbVHtQK7BQkidXGECbSg=", + "dev": true + }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.15" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", + "dev": true + }, + "vary": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", + "integrity": "sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=", + "dev": true + } + } + }, + "express-ws": { + "version": "2.0.0-rc.1", + "resolved": "https://registry.npmjs.org/express-ws/-/express-ws-2.0.0-rc.1.tgz", + "integrity": "sha1-mnx/q98fuNkdvu3MMKbytby3aCY=", + "dev": true, + "requires": { + "ws": "1.1.4" + }, + "dependencies": { + "options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=", + "dev": true + }, + "ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=", + "dev": true + }, + "ws": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.4.tgz", + "integrity": "sha1-V/QNA2gy5fUFVmKjl8Tedu1mv2E=", + "dev": true, + "requires": { + "options": "0.0.6", + "ultron": "1.0.2" + } + } + } + }, + "extend": { + "version": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", + "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=", + "dev": true + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extsprintf": { + "version": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", + "dev": true + }, + "fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "time-stamp": "1.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "forever-agent": { + "version": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "https://registry.npmjs.org/form-data/-/form-data-2.1.2.tgz", + "integrity": "sha1-icNTQAi5fq2ky7FX1Y9vXfAl6uQ=", + "dev": true, + "requires": { + "asynckit": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz" + } + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + } + } + }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.8.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", + "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", + "dev": true + }, + "generate-function": { + "version": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "getpass": { + "version": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", + "integrity": "sha1-KD/9n8ElaECHUxHBtg6MQBhxEOY=", + "dev": true, + "requires": { + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + }, + "dependencies": { + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "graceful-readlink": { + "version": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.0.3", + "liftoff": "2.3.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "dateformat": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", + "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "1.0.2" + } + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "detect-file": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", + "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", + "dev": true, + "requires": { + "fs-exists-sync": "0.1.0" + } + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "1.3.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "expand-tilde": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "findup-sync": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", + "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", + "dev": true, + "requires": { + "detect-file": "0.1.0", + "is-glob": "2.0.1", + "micromatch": "2.3.11", + "resolve-dir": "0.1.1" + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.3", + "object.defaults": "1.1.0", + "object.pick": "1.2.0", + "parse-filepath": "1.0.1" + }, + "dependencies": { + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + } + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", + "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", + "dev": true + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "0.1.0" + } + }, + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.3.3" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "0.5.2" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "0.1.1" + } + }, + "global-modules": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", + "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", + "dev": true, + "requires": { + "global-prefix": "0.1.5", + "is-windows": "0.2.0" + } + }, + "global-prefix": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1", + "ini": "1.3.4", + "is-windows": "0.2.0", + "which": "1.2.14" + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.0" + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.0.0", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.3.3", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "interpret": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", + "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", + "dev": true + }, + "is-absolute": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", + "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "dev": true, + "requires": { + "is-relative": "0.2.1", + "is-windows": "0.2.0" + } + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-relative": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", + "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "dev": true, + "requires": { + "is-unc-path": "0.1.2" + } + }, + "is-unc-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", + "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "dev": true, + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + }, + "liftoff": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", + "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", + "dev": true, + "requires": { + "extend": "3.0.1", + "findup-sync": "0.4.3", + "fined": "1.1.0", + "flagged-respawn": "0.3.2", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.mapvalues": "4.6.0", + "rechoir": "0.6.2", + "resolve": "1.3.3" + } + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.3" + } + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "natives": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", + "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", + "dev": true + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.0.2" + } + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.0" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "parse-filepath": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", + "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", + "dev": true, + "requires": { + "is-absolute": "0.2.6", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.3.3" + } + }, + "regex-cache": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", + "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3", + "is-primitive": "2.0.0" + } + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "resolve": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", + "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", + "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", + "dev": true, + "requires": { + "expand-tilde": "1.2.2", + "global-modules": "0.2.3" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "stream-consume": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", + "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "which": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "gulp-cli": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-1.3.0.tgz", + "integrity": "sha1-pr+7i+NTQb4pCuRc0+QBBxIW7dQ=", + "dev": true, + "requires": { + "archy": "1.0.0", + "chalk": "1.1.3", + "copy-props": "1.6.0", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "interpret": "1.0.3", + "liftoff": "2.3.0", + "lodash.isfunction": "3.0.8", + "lodash.isplainobject": "4.0.6", + "lodash.sortby": "4.7.0", + "matchdep": "1.0.1", + "mute-stdout": "1.0.0", + "pretty-hrtime": "1.0.3", + "semver-greatest-satisfied-range": "1.0.0", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "wreck": "6.3.0", + "yargs": "3.32.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "detect-file": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", + "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", + "dev": true, + "requires": { + "fs-exists-sync": "0.1.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "expand-tilde": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "findup-sync": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", + "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", + "dev": true, + "requires": { + "detect-file": "0.1.0", + "is-glob": "2.0.1", + "micromatch": "2.3.11", + "resolve-dir": "0.1.1" + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.3", + "object.defaults": "1.1.0", + "object.pick": "1.2.0", + "parse-filepath": "1.0.1" + }, + "dependencies": { + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + } + } + }, + "flagged-respawn": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", + "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "global-modules": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", + "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", + "dev": true, + "requires": { + "global-prefix": "0.1.5", + "is-windows": "0.2.0" + } + }, + "global-prefix": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1", + "ini": "1.3.4", + "is-windows": "0.2.0", + "which": "1.2.14" + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "interpret": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", + "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-absolute": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", + "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "dev": true, + "requires": { + "is-relative": "0.2.1", + "is-windows": "0.2.0" + } + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-relative": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", + "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "dev": true, + "requires": { + "is-unc-path": "0.1.2" + } + }, + "is-unc-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", + "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "dev": true, + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "liftoff": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", + "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", + "dev": true, + "requires": { + "extend": "3.0.1", + "findup-sync": "0.4.3", + "fined": "1.1.0", + "flagged-respawn": "0.3.2", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.mapvalues": "4.6.0", + "rechoir": "0.6.2", + "resolve": "1.3.3" + } + }, + "lodash.isfunction": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.8.tgz", + "integrity": "sha1-TbcJ/IG8So/XEnpFilNGxc3OLGs=", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", + "dev": true + }, + "lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "matchdep": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-1.0.1.tgz", + "integrity": "sha1-pXozgESR+64girqPaDgEN6vC3KU=", + "dev": true, + "requires": { + "findup-sync": "0.3.0", + "micromatch": "2.3.11", + "resolve": "1.1.7", + "stack-trace": "0.0.9" + }, + "dependencies": { + "findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "dev": true, + "requires": { + "glob": "5.0.15" + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.3" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "mute-stdout": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.0.tgz", + "integrity": "sha1-WzLqB+tDyd7WEwQ0z5JvRrKn/U0=", + "dev": true + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.0.2" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "parse-filepath": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", + "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", + "dev": true, + "requires": { + "is-absolute": "0.2.6", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.3.3" + } + }, + "regex-cache": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", + "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3", + "is-primitive": "2.0.0" + } + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "resolve": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", + "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", + "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", + "dev": true, + "requires": { + "expand-tilde": "1.2.2", + "global-modules": "0.2.3" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "semver-greatest-satisfied-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.0.0.tgz", + "integrity": "sha1-T7RB4qjSbEC1mDJ1VzGN4nKlWKA=", + "dev": true, + "requires": { + "semver": "4.3.6", + "semver-regex": "1.0.0" + } + }, + "semver-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", + "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=", + "dev": true + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "stack-trace": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", + "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "which": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "wreck": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/wreck/-/wreck-6.3.0.tgz", + "integrity": "sha1-oTaXafB7u2LWo3gzanhx/Hc8dAs=", + "dev": true, + "requires": { + "boom": "2.10.1", + "hoek": "2.16.3" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "os-locale": "1.4.0", + "string-width": "1.0.2", + "window-size": "0.1.4", + "y18n": "3.2.1" + } + } + } + }, + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "1.0.4", + "through2": "2.0.3", + "vinyl": "2.1.0" + }, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "vinyl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "dev": true, + "requires": { + "clone": "2.1.1", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.0.0", + "remove-trailing-separator": "1.0.2", + "replace-ext": "1.0.0" + } + } + } + }, + "gulp-coveralls": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/gulp-coveralls/-/gulp-coveralls-0.1.4.tgz", + "integrity": "sha1-L2IKyN9i0LhrS73mTaNnzEGhkMk=", + "dev": true, + "requires": { + "coveralls": "2.13.1", + "gulp-util": "3.0.8", + "through2": "1.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "coveralls": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.1.tgz", + "integrity": "sha1-1wu5rMGDXsTwY/+drFQjwXsR8Xg=", + "dev": true, + "requires": { + "js-yaml": "3.6.1", + "lcov-parse": "0.0.10", + "log-driver": "1.2.5", + "minimist": "1.2.0", + "request": "2.79.0" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "dateformat": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", + "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extsprintf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", + "dev": true + }, + "fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.0.0", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.0" + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.11.0", + "is-my-json-valid": "2.16.0", + "pinkie-promise": "2.0.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is-my-json-valid": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz", + "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-yaml": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "2.7.3" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "jsprim": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", + "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "lcov-parse": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", + "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "log-driver": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", + "dev": true + }, + "mime-db": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", + "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=", + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", + "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "qs": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "request": { + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.11.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "qs": "6.3.2", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.4.3", + "uuid": "3.1.0" + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "through2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", + "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", + "dev": true, + "requires": { + "readable-stream": "1.1.14", + "xtend": "4.0.1" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "dev": true + }, + "verror": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", + "dev": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "gulp-istanbul": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gulp-istanbul/-/gulp-istanbul-1.1.2.tgz", + "integrity": "sha512-53+BDhGlGNHYfeFh/mSXWhNu9wSFmE8qAEFj6ViMiWzTwI9pYxedUxMmGfigwaddsHHQxBl9TgnzUydrX84Kog==", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "istanbul": "0.4.5", + "istanbul-threshold-checker": "0.2.1", + "lodash": "4.17.4", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "optional": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, + "optional": true + } + } + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "dateformat": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", + "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "optional": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.0.0", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.0" + } + }, + "handlebars": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", + "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.10", + "js-yaml": "3.9.0", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.2.14", + "wordwrap": "1.0.0" + }, + "dependencies": { + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-threshold-checker": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/istanbul-threshold-checker/-/istanbul-threshold-checker-0.2.1.tgz", + "integrity": "sha1-xdyU6PLMXNP/0zVFL4S1U8QkgzE=", + "dev": true, + "requires": { + "istanbul": "0.4.5", + "lodash": "4.17.4" + } + }, + "js-yaml": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.0.tgz", + "integrity": "sha512-0LoUNELX4S+iofCT8f4uEHIiRBR+c2AINyC8qRWfC6QNruLtxVZRJaPcu/xwMgFIgDxF25tGHaDjvxzJCNE9yw==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + } + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true, + "optional": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.0.9" + } + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.10", + "wordwrap": "0.0.3" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.6", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true, + "optional": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "0.5.6" + }, + "dependencies": { + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + } + } + }, + "which": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "gulp-mocha": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/gulp-mocha/-/gulp-mocha-3.0.1.tgz", + "integrity": "sha1-qwyiw5QDcYF03drXUOY6Yb4X4EE=", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "mocha": "3.4.2", + "plur": "2.1.2", + "req-cwd": "1.0.1", + "temp": "0.8.3", + "through": "2.3.8" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "dateformat": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", + "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.0.0", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "irregular-plurals": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-1.3.0.tgz", + "integrity": "sha512-njf5A+Mxb3kojuHd1DzISjjIl+XhyzovXEOyPPSzdQozq/Lf2tN27mOrAAsxEPZxpn6I4MGzs1oo9TxXxPFpaA==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "plur": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/plur/-/plur-2.1.2.tgz", + "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=", + "dev": true, + "requires": { + "irregular-plurals": "1.3.0" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "req-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-1.0.1.tgz", + "integrity": "sha1-DXOurpJm5penj3l2AZZ352rPD/8=", + "dev": true, + "requires": { + "req-from": "1.0.1" + } + }, + "req-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/req-from/-/req-from-1.0.1.tgz", + "integrity": "sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4=", + "dev": true, + "requires": { + "resolve-from": "2.0.0" + } + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", + "dev": true + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "temp": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2", + "rimraf": "2.2.8" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "gulp-sourcemaps": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.9.1.tgz", + "integrity": "sha1-gKwtOEXRPmjdliUk2KlnpECwt1M=", + "dev": true, + "requires": { + "acorn": "4.0.13", + "convert-source-map": "1.5.0", + "css": "2.2.1", + "debug-fabulous": "0.0.4", + "detect-newline": "2.1.0", + "graceful-fs": "4.1.11", + "source-map": "0.5.6", + "strip-bom": "2.0.0", + "through2": "2.0.3", + "vinyl": "1.2.0" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "atob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", + "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", + "dev": true + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "css": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "source-map": "0.1.43", + "source-map-resolve": "0.3.1", + "urix": "0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "debug-fabulous": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-0.0.4.tgz", + "integrity": "sha1-+gccXYdIRoVCSAdCHKSxawsaB2M=", + "dev": true, + "requires": { + "debug": "2.6.8", + "lazy-debug-legacy": "0.0.1", + "object-assign": "4.1.0" + } + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "lazy-debug-legacy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/lazy-debug-legacy/-/lazy-debug-legacy-0.0.1.tgz", + "integrity": "sha1-U3cWwHduTPeePtG2IfdljCkRsbE=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "object-assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", + "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + }, + "source-map-resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", + "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", + "dev": true, + "requires": { + "atob": "1.1.3", + "resolve-url": "0.2.1", + "source-map-url": "0.3.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", + "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", + "dev": true + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "gulp-typescript": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-3.2.0.tgz", + "integrity": "sha1-jd975ljRMBiDgfZablgMVStkwZY=", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "source-map": "0.5.6", + "through2": "2.0.3", + "vinyl-fs": "2.4.4" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "dateformat": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", + "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "duplexify": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz", + "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=", + "dev": true, + "requires": { + "end-of-stream": "1.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "stream-shift": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "end-of-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", + "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=", + "dev": true, + "requires": { + "once": "1.3.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + } + } + }, + "fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + } + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "3.0.1", + "glob": "5.0.15", + "glob-parent": "3.1.0", + "micromatch": "2.3.11", + "ordered-read-streams": "0.3.0", + "through2": "0.6.5", + "to-absolute-glob": "0.1.1", + "unique-stream": "2.2.1" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "gulp-sourcemaps": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", + "dev": true, + "requires": { + "convert-source-map": "1.5.0", + "graceful-fs": "4.1.11", + "strip-bom": "2.0.0", + "through2": "2.0.3", + "vinyl": "1.2.0" + }, + "dependencies": { + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.0.0", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.3.3", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.3" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.0.2" + } + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "readable-stream": "2.3.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "regex-cache": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", + "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3", + "is-primitive": "2.0.0" + } + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-bom-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", + "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "strip-bom": "2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true, + "requires": { + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "to-absolute-glob": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1" + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "1.0.1", + "through2-filter": "2.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "dev": true + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "3.5.0", + "glob-stream": "5.3.5", + "graceful-fs": "4.1.11", + "gulp-sourcemaps": "1.6.0", + "is-valid-glob": "0.3.0", + "lazystream": "1.0.0", + "lodash.isequal": "4.5.0", + "merge-stream": "1.0.1", + "mkdirp": "0.5.1", + "object-assign": "4.1.1", + "readable-stream": "2.3.3", + "strip-bom": "2.0.0", + "strip-bom-stream": "1.0.0", + "through2": "2.0.3", + "through2-filter": "2.0.0", + "vali-date": "1.0.0", + "vinyl": "1.2.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.0.0", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.0" + } + }, + "har-validator": { + "version": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "commander": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "is-my-json-valid": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz", + "pinkie-promise": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + }, + "dependencies": { + "commander": { + "version": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" + } + } + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true, + "requires": { + "function-bind": "1.1.0" + } + }, + "has-ansi": { + "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "hawk": { + "version": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "cryptiles": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "sntp": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + }, + "dependencies": { + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + } + } + }, + "hoek": { + "version": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.1.tgz", + "integrity": "sha1-eb96eF6klf5mFl5zQVPzY/9UN9o=", + "dev": true, + "requires": { + "whatwg-encoding": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz" + } + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "dev": true + }, + "http-signature": { + "version": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "jsprim": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz", + "sshpk": "https://registry.npmjs.org/sshpk/-/sshpk-1.10.2.tgz" + } + }, + "https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", + "dev": true + }, + "iconv-lite": { + "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", + "dev": true + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "dev": true + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "dev": true, + "requires": { + "source-map": "0.5.6" + } + }, + "insert-module-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.1.tgz", + "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", + "dev": true, + "requires": { + "JSONStream": "1.3.1", + "combine-source-map": "0.7.2", + "concat-stream": "1.5.2", + "is-buffer": "1.1.5", + "lexical-scope": "1.2.0", + "process": "0.11.10", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-my-json-valid": { + "version": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz", + "integrity": "sha1-k27do8o8IR/ZjzstPgjaQ/eykVs=", + "dev": true, + "requires": { + "generate-function": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "generate-object-property": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "jsonpointer": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "xtend": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-plain-object": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.3.tgz", + "integrity": "sha1-wVvz5LZrYtcu+vKSWEhmPsvGGbY=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-property": { + "version": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-typedarray": { + "version": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "isstream": { + "version": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jodid25519": { + "version": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", + "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" + } + }, + "jsbn": { + "version": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jsdoc": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.4.3.tgz", + "integrity": "sha1-5XQNYUXGgfZnnmwXeDqI292XzNM=", + "dev": true, + "requires": { + "bluebird": "3.4.7", + "catharsis": "0.8.8", + "escape-string-regexp": "1.0.5", + "espree": "3.1.7", + "js2xmlparser": "1.0.0", + "klaw": "1.3.1", + "marked": "0.3.6", + "mkdirp": "0.5.1", + "requizzle": "0.2.1", + "strip-json-comments": "2.0.1", + "taffydb": "2.6.2", + "underscore": "1.8.3" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + } + }, + "bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", + "dev": true + }, + "catharsis": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.8.tgz", + "integrity": "sha1-aTR59DqsVJ2Aa9c+kkzQ2USVGgY=", + "dev": true, + "requires": { + "underscore-contrib": "0.3.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "espree": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.1.7.tgz", + "integrity": "sha1-/V3ux2qXpRIKnNOnyxF3oJI7EdI=", + "dev": true, + "requires": { + "acorn": "3.3.0", + "acorn-jsx": "3.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true, + "optional": true + }, + "js2xmlparser": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-1.0.0.tgz", + "integrity": "sha1-WhcPLo1kds5FQF4EgjJCUTeC/jA=", + "dev": true + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "marked": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz", + "integrity": "sha1-ssbGGPzOzk74bE/Gy4p8v1rtqNc=", + "dev": true + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "requizzle": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", + "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=", + "dev": true, + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + } + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", + "dev": true + }, + "underscore-contrib": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz", + "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=", + "dev": true, + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + } + } + } + } + }, + "jsdom": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.1.0.tgz", + "integrity": "sha512-vKKDU+Xh9O6VgzdOYf5Rmqbgp+Yz4YTBC19gaLtctXch33EmNucA395KJGGboldafPW1vv9XLuiprO4+wXfl0g==", + "dev": true, + "requires": { + "abab": "https://registry.npmjs.org/abab/-/abab-1.0.3.tgz", + "acorn": "4.0.13", + "acorn-globals": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", + "array-equal": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "content-type-parser": "https://registry.npmjs.org/content-type-parser/-/content-type-parser-1.0.1.tgz", + "cssom": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz", + "cssstyle": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", + "escodegen": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "html-encoding-sniffer": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.1.tgz", + "nwmatcher": "1.4.1", + "parse5": "3.0.2", + "pn": "1.0.0", + "request": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "request-promise-native": "1.0.4", + "sax": "https://registry.npmjs.org/sax/-/sax-1.2.2.tgz", + "symbol-tree": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "tough-cookie": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "webidl-conversions": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.1.tgz", + "whatwg-encoding": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz", + "whatwg-url": "6.1.0", + "xml-name-validator": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + }, + "nwmatcher": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.1.tgz", + "integrity": "sha1-eumwew6oBNt+JfBctf5Al9TklJ8=", + "dev": true + }, + "parse5": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.2.tgz", + "integrity": "sha1-Be/1fw70V3+xRKefi5qWemzERRA=", + "dev": true, + "requires": { + "@types/node": "6.0.79" + } + }, + "whatwg-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.1.0.tgz", + "integrity": "sha1-X8gnm5PXVIO5ztiyYjmFSEehhXg=", + "dev": true, + "requires": { + "lodash.sortby": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "tr46": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "webidl-conversions": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.1.tgz" + } + } + } + }, + "json-loader": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", + "dev": true + }, + "json-schema": { + "version": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsonpointer": { + "version": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "jsprim": { + "version": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz", + "integrity": "sha1-KnJW9wQSop7jZwqspiWZTE3P8lI=", + "dev": true, + "requires": { + "extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "json-schema": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "verror": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + }, + "labeled-stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz", + "integrity": "sha1-pS4dE4AkwAuGscDJH2d5GLiuClk=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "isarray": "0.0.1", + "stream-splicer": "2.0.0" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "levn": { + "version": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "type-check": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz" + } + }, + "lexical-scope": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", + "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", + "dev": true, + "requires": { + "astw": "2.2.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", + "dev": true + }, + "lodash.sortby": { + "version": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "make-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.0.0.tgz", + "integrity": "sha1-l6ARdR6R3YfPre9Ygy67BJNt6Xg=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "0.1.6", + "readable-stream": "2.3.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + } + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "miller-rabin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.0.tgz", + "integrity": "sha1-SmL7HUKTPAVYOYL0xxb2+55sbT0=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "brorand": "1.1.0" + } + }, + "mime-db": { + "version": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz", + "integrity": "sha1-6v/NDk/Gk1z4E02iRuLmw1MFrf8=", + "dev": true + }, + "mime-types": { + "version": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz", + "integrity": "sha1-9+99l1g/yvO30oK2+LVnnaselO4=", + "dev": true, + "requires": { + "mime-db": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz" + } + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "mocha": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.4.2.tgz", + "integrity": "sha1-0O9NMyEm2/GNDWQMmzgt1IvpdZQ=", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.0", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "debug": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", + "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=", + "dev": true, + "requires": { + "ms": "0.7.2" + } + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } + }, + "module-deps": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", + "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", + "dev": true, + "requires": { + "JSONStream": "1.3.1", + "browser-resolve": "1.11.2", + "cached-path-relative": "1.0.1", + "concat-stream": "1.5.2", + "defined": "1.0.0", + "detective": "4.5.0", + "duplexer2": "0.1.4", + "inherits": "2.0.3", + "parents": "1.0.1", + "readable-stream": "2.3.3", + "resolve": "1.4.0", + "stream-combiner2": "1.1.1", + "subarg": "1.0.0", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "dev": true + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "1.4.1", + "browserify-zlib": "0.2.0", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.11.1", + "domain-browser": "1.1.7", + "events": "1.1.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.3", + "stream-browserify": "2.0.1", + "stream-http": "2.7.2", + "string_decoder": "1.0.3", + "timers-browserify": "2.0.4", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "1.0.6" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "timers-browserify": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz", + "integrity": "sha512-uZYhyU3EX8O7HQP+J9fTVYwsq90Vr68xPEFo7yrVImIxYvHgukBEgOB/SgGoorWVTzGM/3Z+wUNnboA4M8jWrg==", + "dev": true, + "requires": { + "setimmediate": "1.0.5" + } + } + } + }, + "node-pty": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/node-pty/-/node-pty-0.7.3.tgz", + "integrity": "sha1-S7NqJKYu6fMzLi4jENZkLZ2u0fc=", + "dev": true, + "requires": { + "nan": "2.8.0" + } + }, + "nodemon": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.10.2.tgz", + "integrity": "sha1-7FEeFMOtCFj8EhxgBokO0nt8QS4=", + "dev": true, + "requires": { + "chokidar": "1.7.0", + "debug": "2.6.8", + "es6-promise": "3.3.1", + "ignore-by-default": "1.0.1", + "lodash.defaults": "3.1.2", + "minimatch": "3.0.4", + "ps-tree": "1.1.0", + "touch": "1.0.0", + "undefsafe": "0.0.3", + "update-notifier": "0.5.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz", + "integrity": "sha1-o+Uvo5FoyCX/V7AkgSbOWo/5VQc=", + "dev": true, + "requires": { + "arrify": "1.0.1", + "micromatch": "2.3.11" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "binary-extensions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.8.0.tgz", + "integrity": "sha1-SOyNFt9Dd+rl+liEaCSAr02Vx3Q=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.0", + "async-each": "1.0.1", + "fsevents": "1.1.3", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "configstore": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-1.4.0.tgz", + "integrity": "sha1-w1eB0FAdJowlxUuLF/YkDopPsCE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "object-assign": "4.1.1", + "os-tmpdir": "1.0.2", + "osenv": "0.1.4", + "uuid": "2.0.3", + "write-file-atomic": "1.3.4", + "xdg-basedir": "2.0.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexify": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz", + "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=", + "dev": true, + "requires": { + "end-of-stream": "1.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "stream-shift": "1.0.0" + } + }, + "end-of-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", + "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=", + "dev": true, + "requires": { + "once": "1.3.3" + } + }, + "es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "requires": { + "duplexer": "0.1.1", + "from": "0.1.7", + "map-stream": "0.1.0", + "pause-stream": "0.0.11", + "split": "0.3.3", + "stream-combiner": "0.0.4", + "through": "2.3.8" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "got": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/got/-/got-3.3.1.tgz", + "integrity": "sha1-5dDtSvVfw+701WAHdp2YGSvLLso=", + "dev": true, + "requires": { + "duplexify": "3.5.0", + "infinity-agent": "2.0.3", + "is-redirect": "1.0.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.0", + "nested-error-stacks": "1.0.2", + "object-assign": "3.0.0", + "prepend-http": "1.0.4", + "read-all-stream": "3.1.0", + "timed-out": "2.0.0" + }, + "dependencies": { + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "infinity-agent": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/infinity-agent/-/infinity-agent-2.0.3.tgz", + "integrity": "sha1-ReDi/3qesDCyfWK3SzdEt6esQhY=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.8.0" + } + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + }, + "latest-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-1.0.1.tgz", + "integrity": "sha1-cs/Ebj6NG+ZR4eu1Tqn26pbzdLs=", + "dev": true, + "requires": { + "package-json": "1.2.0" + } + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", + "dev": true + }, + "lodash._createassigner": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", + "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", + "dev": true, + "requires": { + "lodash._bindcallback": "3.0.1", + "lodash._isiterateecall": "3.0.9", + "lodash.restparam": "3.6.1" + } + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash.assign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", + "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._createassigner": "3.1.1", + "lodash.keys": "3.1.2" + } + }, + "lodash.defaults": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-3.1.2.tgz", + "integrity": "sha1-xzCLGNv4vJNy1wGnNJPGEZK9Liw=", + "dev": true, + "requires": { + "lodash.assign": "3.2.0", + "lodash.restparam": "3.6.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "dev": true + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.3" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nested-error-stacks": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-1.0.2.tgz", + "integrity": "sha1-GfYZWRUZ8JZ2mlupqG5u7sgjw88=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1.1.0" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.0.2" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "package-json": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-1.2.0.tgz", + "integrity": "sha1-yOysCUInzfdqMWh07QXifMk5oOA=", + "dev": true, + "requires": { + "got": "3.3.1", + "registry-url": "3.1.0" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "ps-tree": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz", + "integrity": "sha1-tCGyQUDWID8e08dplrRCewjowBQ=", + "dev": true, + "requires": { + "event-stream": "3.3.4" + } + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "dev": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "read-all-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", + "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1", + "readable-stream": "2.3.3" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + } + }, + "regex-cache": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", + "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3", + "is-primitive": "2.0.0" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "1.2.1" + } + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", + "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "5.3.0" + } + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "0.1.1" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "string-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz", + "integrity": "sha1-VpcPscOFWOnnC3KL894mmsRa36w=", + "dev": true, + "requires": { + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "timed-out": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-2.0.0.tgz", + "integrity": "sha1-84sK6B03R9YoAB9B2vxlKs5nHAo=", + "dev": true + }, + "touch": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-1.0.0.tgz", + "integrity": "sha1-RJy+LbrlqMgDjjDXH6D/RklHxN4=", + "dev": true, + "requires": { + "nopt": "1.0.10" + } + }, + "undefsafe": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-0.0.3.tgz", + "integrity": "sha1-7Mo6A+VrmvFzhbqsgSrIO5lKli8=", + "dev": true + }, + "update-notifier": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-0.5.0.tgz", + "integrity": "sha1-B7XcIGazYnqztPUwEw9+3doHpMw=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "configstore": "1.4.0", + "is-npm": "1.0.0", + "latest-version": "1.0.1", + "repeating": "1.1.3", + "semver-diff": "2.1.0", + "string-length": "1.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", + "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } + }, + "xdg-basedir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-2.0.0.tgz", + "integrity": "sha1-7byQPMOF/ARSPZZqM1UEtVBNG9I=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + } + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.0.2" + } + }, + "npm-run-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", + "integrity": "sha1-9cMr9ZX+ga6Sfa7FLoL4sACsPI8=", + "dev": true, + "requires": { + "path-key": "1.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.0.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.2.0.tgz", + "integrity": "sha1-tTkr7peC2m2ft9avr1OXefEjTCs=", + "dev": true, + "requires": { + "isobject": "2.1.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "optionator": { + "version": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "fast-levenshtein": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "levn": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "prelude-ls": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "type-check": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "wordwrap": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" + }, + "dependencies": { + "wordwrap": { + "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "os-browserify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", + "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + }, + "dependencies": { + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + } + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.2.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, + "requires": { + "asn1.js": "4.9.1", + "browserify-aes": "1.0.6", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.0", + "pbkdf2": "3.0.12" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", + "integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "pbkdf2": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.12.tgz", + "integrity": "sha1-vjZ4XFBn6kjYBv+SMojF91C2uKI=", + "dev": true, + "requires": { + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.8" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + } + }, + "pn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.0.0.tgz", + "integrity": "sha1-HPWjCw2AbNGPiPxBprXUrWFbO6k=", + "dev": true + }, + "prelude-ls": { + "version": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "printj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.0.tgz", + "integrity": "sha512-NbiNBOQ0GioHyeD3ni8wZB7ZmfU7mxIrqhWR5XSreX3rUVvk5UOwpzxOnWqrLdCtoBbdQ40sEwC+nXxxjlUo0A==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, + "requires": { + "bn.js": "4.11.7", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "parse-asn1": "5.1.0", + "randombytes": "2.0.5" + } + }, + "punycode": { + "version": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "randombytes": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", + "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz", + "integrity": "sha1-abBi2XhyetFNxrVrpKt3L9jXBRE=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "request": { + "version": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", + "dev": true, + "requires": { + "aws-sign2": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "aws4": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "caseless": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "combined-stream": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "extend": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", + "forever-agent": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "form-data": "https://registry.npmjs.org/form-data/-/form-data-2.1.2.tgz", + "har-validator": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "hawk": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "http-signature": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "is-typedarray": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "isstream": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "json-stringify-safe": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "mime-types": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz", + "oauth-sign": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "qs": "https://registry.npmjs.org/qs/-/qs-6.3.1.tgz", + "stringstream": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "tough-cookie": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "tunnel-agent": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "uuid": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz" + }, + "dependencies": { + "qs": { + "version": "https://registry.npmjs.org/qs/-/qs-6.3.1.tgz", + "integrity": "sha1-kYwLO802Z5dyuvE1say0wWUe150=", + "dev": true + }, + "uuid": { + "version": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", + "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=", + "dev": true + } + } + }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "dev": true, + "requires": { + "lodash": "4.17.4" + }, + "dependencies": { + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + } + } + }, + "request-promise-native": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.4.tgz", + "integrity": "sha1-hpiOyO7kCORVefzoO/0Fs635oVU=", + "dev": true, + "requires": { + "request-promise-core": "1.1.1", + "stealthy-require": "1.1.1", + "tough-cookie": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "resolve": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "0.1.4" + } + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "sax": { + "version": "https://registry.npmjs.org/sax/-/sax-1.2.2.tgz", + "integrity": "sha1-/YYxojvHgmvvXYcb24c3jJVkeCg=", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "sha.js": { + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.8.tgz", + "integrity": "sha1-NwaMLEdra69ALRSknGf1l5IfY08=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "shasum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "dev": true, + "requires": { + "json-stable-stringify": "0.0.1", + "sha.js": "2.4.8" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "requires": { + "array-filter": "0.0.1", + "array-map": "0.0.0", + "array-reduce": "0.0.0", + "jsonify": "0.0.0" + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sntp": { + "version": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + } + }, + "sorcery": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz", + "integrity": "sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13", + "minimist": "1.2.0", + "sander": "0.5.1", + "sourcemap-codec": "1.3.1" + }, + "dependencies": { + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "sander": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", + "integrity": "sha1-dB4kXiMfB8r7b98PEzrfohalAq0=", + "dev": true, + "requires": { + "es6-promise": "3.3.1", + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "sourcemap-codec": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.3.1.tgz", + "integrity": "sha1-mtb5vb1pGTEBbjCTnbyGhnMyMUY=", + "dev": true, + "requires": { + "vlq": "0.2.2" + } + }, + "vlq": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.2.tgz", + "integrity": "sha1-4xbVJXtAuGu0PLjV/qXX9U1rDKE=", + "dev": true + } + } + }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "dev": true + }, + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "sshpk": { + "version": "https://registry.npmjs.org/sshpk/-/sshpk-1.10.2.tgz", + "integrity": "sha1-1agEziJpVRVjjnmNviMnPeBwpfo=", + "dev": true, + "requires": { + "asn1": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "assert-plus": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "bcrypt-pbkdf": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "dashdash": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "ecc-jsbn": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "getpass": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", + "jodid25519": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", + "jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "tweetnacl": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" + }, + "dependencies": { + "assert-plus": { + "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "0.1.4", + "readable-stream": "2.3.3" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "stream-http": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", + "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", + "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "stringstream": { + "version": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "requires": { + "minimist": "1.2.0" + } + }, + "supports-color": { + "version": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "symbol-tree": { + "version": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", + "dev": true + }, + "syntax-error": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz", + "integrity": "sha1-HtkmbE1AvnXcVb+bsct3Biu5bKE=", + "dev": true, + "requires": { + "acorn": "4.0.13" + } + }, + "tapable": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", + "dev": true + }, + "term-size": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-0.1.1.tgz", + "integrity": "sha1-hzYLljlsq1dgljcUzaDQy+7K2co=", + "dev": true, + "requires": { + "execa": "0.4.0" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true, + "requires": { + "process": "0.11.10" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "tough-cookie": { + "version": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "dev": true, + "requires": { + "punycode": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" + } + }, + "tr46": { + "version": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "tslint": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-4.5.1.tgz", + "integrity": "sha1-BTVocb7yOkNJBnNABvwYgza6gks=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "colors": "1.1.2", + "diff": "3.3.0", + "findup-sync": "0.3.0", + "glob": "7.1.2", + "optimist": "0.6.1", + "resolve": "1.3.3", + "tsutils": "1.9.1", + "update-notifier": "2.2.0" + }, + "dependencies": { + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "requires": { + "string-width": "2.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "boxen": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.1.0.tgz", + "integrity": "sha1-sbad1SIwXoB6md7ud329blFnsQI=", + "dev": true, + "requires": { + "ansi-align": "2.0.0", + "camelcase": "4.1.0", + "chalk": "1.1.3", + "cli-boxes": "1.0.0", + "string-width": "2.1.0", + "term-size": "0.1.1", + "widest-line": "1.0.0" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "configstore": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.0.tgz", + "integrity": "sha1-Rd+QcHPibfoc9LLVL1tgVF6qEdE=", + "dev": true, + "requires": { + "dot-prop": "4.1.1", + "graceful-fs": "4.1.11", + "make-dir": "1.0.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.1.0", + "xdg-basedir": "3.0.0" + } + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, + "diff": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.0.tgz", + "integrity": "sha512-w0XZubFWn0Adlsapj9EAWX0FqWdO4tz8kc3RiYdWLh4k/V8PTb6i0SMgXt0vRM3zyKnT8tKO7mUlieRQHIjMNg==", + "dev": true + }, + "dot-prop": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.1.1.tgz", + "integrity": "sha1-qEk/C3te7sglJbXHWH+n3nyoWcE=", + "dev": true, + "requires": { + "is-obj": "1.0.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "dev": true, + "requires": { + "glob": "5.0.15" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + } + } + }, + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "dev": true, + "requires": { + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.0", + "safe-buffer": "5.1.1", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "dev": true + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "dev": true, + "requires": { + "package-json": "4.0.1" + } + }, + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.10", + "wordwrap": "0.0.3" + } + }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "dev": true, + "requires": { + "got": "6.7.1", + "registry-auth-token": "3.3.1", + "registry-url": "3.1.0", + "semver": "5.3.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "dev": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "registry-auth-token": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.1.tgz", + "integrity": "sha1-+w0yie4Nmtosu1KvXf5mywcNMAY=", + "dev": true, + "requires": { + "rc": "1.2.1", + "safe-buffer": "5.1.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "1.2.1" + } + }, + "resolve": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", + "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "5.3.0" + } + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, + "string-width": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.0.tgz", + "integrity": "sha1-AwZkVh/BRslCPsfZeP4kV0N/5tA=", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true + }, + "update-notifier": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.2.0.tgz", + "integrity": "sha1-G1g3z5DAc22IYncytmHBOPht5y8=", + "dev": true, + "requires": { + "boxen": "1.1.0", + "chalk": "1.1.3", + "configstore": "3.1.0", + "import-lazy": "2.1.0", + "is-npm": "1.0.0", + "latest-version": "3.1.0", + "semver-diff": "2.1.0", + "xdg-basedir": "3.0.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "1.0.4" + } + }, + "widest-line": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-1.0.0.tgz", + "integrity": "sha1-DAnIXCqUaD0Nfq+O4JfVZL8OEFw=", + "dev": true, + "requires": { + "string-width": "1.0.2" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.1.0.tgz", + "integrity": "sha512-0TZ20a+xcIl4u0+Mj5xDH2yOWdmQiXlKf9Hm+TgDXjTMsEYb+gDrmb8e8UNAzMCitX8NBqG4Z/FUQIyzv/R1JQ==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true + } + } + }, + "tsutils": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-1.9.1.tgz", + "integrity": "sha1-ufmrROVa+WgYMdXyjQrur1x1DLA=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "tweetnacl": { + "version": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-check": { + "version": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.4.2.tgz", + "integrity": "sha1-+DlfhdRZJ2BnyYiqQYN6j4KHCEQ=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "0.5.6", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "0.5.6", + "uglify-js": "2.8.29", + "webpack-sources": "1.1.0" + } + }, + "umd": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.1.tgz", + "integrity": "sha1-iuVW4RAR9jwllnCKiDclnwGz1g4=", + "dev": true + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "1.0.0" + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "verror": { + "version": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", + "dev": true, + "requires": { + "extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vinyl-buffer/-/vinyl-buffer-1.0.0.tgz", + "integrity": "sha1-ygZ+oIQx1QdyKx3lCD9gJhbrwjQ=", + "dev": true, + "requires": { + "bl": "0.9.5", + "through2": "0.6.5" + }, + "dependencies": { + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "dev": true, + "requires": { + "readable-stream": "1.0.34" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "vinyl-source-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz", + "integrity": "sha1-RMvlEIIFJ53rDFZTwJSiiHk4sas=", + "dev": true, + "requires": { + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "watchpack": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", + "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", + "dev": true, + "requires": { + "async": "2.6.0", + "chokidar": "1.7.0", + "graceful-fs": "4.1.11" + } + }, + "webidl-conversions": { + "version": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.1.tgz", + "integrity": "sha1-gBWherg+fhsxFjhIas6B2mziBqA=", + "dev": true + }, + "webpack": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.10.0.tgz", + "integrity": "sha512-fxxKXoicjdXNUMY7LIdY89tkJJJ0m1Oo8PQutZ5rLgWbV5QVKI15Cn7+/IHnRTd3vfKfiwBx6SBqlorAuNA8LA==", + "dev": true, + "requires": { + "acorn": "5.3.0", + "acorn-dynamic-import": "2.0.2", + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "async": "2.6.0", + "enhanced-resolve": "3.4.1", + "escope": "3.6.0", + "interpret": "1.1.0", + "json-loader": "0.5.7", + "json5": "0.5.1", + "loader-runner": "2.3.0", + "loader-utils": "1.1.0", + "memory-fs": "0.4.1", + "mkdirp": "0.5.1", + "node-libs-browser": "2.1.0", + "source-map": "0.5.6", + "supports-color": "4.5.0", + "tapable": "0.2.8", + "uglifyjs-webpack-plugin": "0.4.6", + "watchpack": "1.4.0", + "webpack-sources": "1.1.0", + "yargs": "8.0.2" + }, + "dependencies": { + "acorn": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", + "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "webpack-sources": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true, + "requires": { + "source-list-map": "2.0.0", + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "webpack-stream": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-4.0.0.tgz", + "integrity": "sha1-82c92QfW2bHqe/UfzR24W1/Z4PI=", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "lodash.clone": "4.5.0", + "lodash.some": "4.6.0", + "memory-fs": "0.4.1", + "through": "2.3.8", + "vinyl": "2.1.0", + "webpack": "3.10.0" + }, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "vinyl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "dev": true, + "requires": { + "clone": "2.1.1", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.0.0", + "remove-trailing-separator": "1.0.2", + "replace-ext": "1.0.0" + } + } + } + }, + "whatwg-encoding": { + "version": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz", + "integrity": "sha1-PGxFGhmO567FWx7GHQkgxngBpfQ=", + "dev": true, + "requires": { + "iconv-lite": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz" + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } + } + }, + "xml-name-validator": { + "version": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", + "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=", + "dev": true + }, + "xtend": { + "version": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + }, + "zmodem.js": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/zmodem.js/-/zmodem.js-0.1.6.tgz", + "integrity": "sha1-QNeLS0uYQiBo5CB5II/wgFcLrdk=", + "dev": true, + "requires": { + "crc-32": "1.1.1" + } + } + } +} diff --git a/xterm.js/package.json b/xterm.js/package.json new file mode 100644 index 0000000..1dfadf9 --- /dev/null +++ b/xterm.js/package.json @@ -0,0 +1,91 @@ +{ + "name": "xterm", + "description": "Full xterm terminal, in your browser", + "version": "3.0.0", + "ignore": [ + "demo", + "test", + ".gitignore" + ], + "main": "lib/Terminal.js", + "types": "typings/xterm.d.ts", + "repository": "https://github.com/xtermjs/xterm.js", + "license": "MIT", + "files": [ + "*.js", + "*.json", + "dist/*.css", + "dist/**/*.css", + "dist/*.js", + "dist/*.js.map", + "dist/**/*.js", + "dist/**/*.js.map", + "lib/*.css", + "lib/**/*.css", + "lib/*.d.ts", + "lib/*.js", + "lib/*.js.map", + "lib/**/*.d.ts", + "lib/**/*.js", + "lib/**/*.js.map", + "src/*.css", + "src/**/*.css", + "src/*.js", + "src/*.js.map", + "src/*.ts", + "src/**/*.js", + "src/**/*.js.map", + "src/**/*.ts", + "typings/*.d.ts" + ], + "devDependencies": { + "@types/chai": "^3.4.34", + "@types/jsdom": "^11.0.1", + "@types/mocha": "^2.2.33", + "@types/node": "^6.0.41", + "@types/text-encoding": "0.0.32", + "browserify": "^13.3.0", + "chai": "3.5.0", + "docdash": "0.4.0", + "express": "4.13.4", + "express-ws": "2.0.0-rc.1", + "fs-extra": "^1.0.0", + "glob": "^7.0.5", + "gulp": "3.9.1", + "gulp-cli": "^1.2.2", + "gulp-concat": "^2.6.1", + "gulp-coveralls": "^0.1.4", + "gulp-istanbul": "^1.1.1", + "gulp-mocha": "^3.0.1", + "gulp-sourcemaps": "1.9.1", + "gulp-typescript": "^3.1.3", + "gulp-util": "3.0.8", + "jsdoc": "3.4.3", + "jsdom": "^11.1.0", + "merge-stream": "^1.0.1", + "node-pty": "^0.7.2", + "nodemon": "1.10.2", + "sorcery": "^0.10.0", + "tslint": "^4.0.2", + "typescript": "~2.4.0", + "vinyl-buffer": "^1.0.0", + "vinyl-source-stream": "^1.1.0", + "webpack": "^3.10.0", + "webpack-stream": "^4.0.0", + "zmodem.js": "^0.1.5" + }, + "scripts": { + "prestart": "gulp webpack", + "start": "node demo/app", + "prestart-zmodem": "npm run build", + "start-zmodem": "node build/addons/zmodem/demo/app", + "lint": "tslint src/*.ts src/**/*.ts", + "test": "gulp test", + "build:docs": "jsdoc -c jsdoc.json", + "build": "gulp build", + "prepublish": "npm run build", + "coveralls": "gulp coveralls", + "webpack": "gulp webpack" + }, + "dependencies": {} +} diff --git a/xterm.js/src/Buffer.test.ts b/xterm.js/src/Buffer.test.ts new file mode 100644 index 0000000..210d297 --- /dev/null +++ b/xterm.js/src/Buffer.test.ts @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert } from 'chai'; +import { ITerminal } from './Interfaces'; +import { Buffer } from './Buffer'; +import { CircularList } from './utils/CircularList'; +import { MockTerminal } from './utils/TestUtils.test'; + +const INIT_COLS = 80; +const INIT_ROWS = 24; + +describe('Buffer', () => { + let terminal: ITerminal; + let buffer: Buffer; + + beforeEach(() => { + terminal = new MockTerminal(); + terminal.cols = INIT_COLS; + terminal.rows = INIT_ROWS; + terminal.options.scrollback = 1000; + buffer = new Buffer(terminal, true); + }); + + describe('constructor', () => { + it('should create a CircularList with max length equal to rows + scrollback, for its lines', () => { + assert.instanceOf(buffer.lines, CircularList); + assert.equal(buffer.lines.maxLength, terminal.rows + terminal.options.scrollback); + }); + it('should set the Buffer\'s scrollBottom value equal to the terminal\'s rows -1', () => { + assert.equal(buffer.scrollBottom, terminal.rows - 1); + }); + }); + + describe('fillViewportRows', () => { + it('should fill the buffer with blank lines based on the size of the viewport', () => { + const blankLineChar = terminal.blankLine()[0]; + buffer.fillViewportRows(); + assert.equal(buffer.lines.length, INIT_ROWS); + for (let y = 0; y < INIT_ROWS; y++) { + assert.equal(buffer.lines.get(y).length, INIT_COLS); + for (let x = 0; x < INIT_COLS; x++) { + assert.deepEqual(buffer.lines.get(y)[x], blankLineChar); + } + } + }); + }); + + describe('resize', () => { + describe('column size is reduced', () => { + it('should not trim the data in the buffer', () => { + buffer.fillViewportRows(); + buffer.resize(INIT_COLS / 2, INIT_ROWS); + assert.equal(buffer.lines.length, INIT_ROWS); + for (let i = 0; i < INIT_ROWS; i++) { + assert.equal(buffer.lines.get(i).length, INIT_COLS); + } + }); + }); + + describe('column size is increased', () => { + it('should add pad columns', () => { + buffer.fillViewportRows(); + buffer.resize(INIT_COLS + 10, INIT_ROWS); + assert.equal(buffer.lines.length, INIT_ROWS); + for (let i = 0; i < INIT_ROWS; i++) { + assert.equal(buffer.lines.get(i).length, INIT_COLS + 10); + } + }); + }); + + describe('row size reduced', () => { + it('should trim blank lines from the end', () => { + buffer.fillViewportRows(); + buffer.resize(INIT_COLS, INIT_ROWS - 10); + assert.equal(buffer.lines.length, INIT_ROWS - 10); + }); + + it('should move the viewport down when it\'s at the end', () => { + buffer.fillViewportRows(); + // Set cursor y to have 5 blank lines below it + buffer.y = INIT_ROWS - 5 - 1; + buffer.resize(INIT_COLS, INIT_ROWS - 10); + // Trim 5 rows + assert.equal(buffer.lines.length, INIT_ROWS - 5); + // Shift the viewport down 5 rows + assert.equal(buffer.ydisp, 5); + assert.equal(buffer.ybase, 5); + }); + + describe('no scrollback', () => { + it('should trim from the top of the buffer when the cursor reaches the bottom', () => { + terminal.options.scrollback = 0; + buffer = new Buffer(terminal, true); + assert.equal(buffer.lines.maxLength, INIT_ROWS); + buffer.y = INIT_ROWS - 1; + buffer.fillViewportRows(); + buffer.lines.get(5)[0][1] = 'a'; + buffer.lines.get(INIT_ROWS - 1)[0][1] = 'b'; + buffer.resize(INIT_COLS, INIT_ROWS - 5); + assert.equal(buffer.lines.get(0)[0][1], 'a'); + assert.equal(buffer.lines.get(INIT_ROWS - 1 - 5)[0][1], 'b'); + }); + }); + }); + + describe('row size increased', () => { + describe('empty buffer', () => { + it('should add blank lines to end', () => { + buffer.fillViewportRows(); + assert.equal(buffer.ydisp, 0); + buffer.resize(INIT_COLS, INIT_ROWS + 10); + assert.equal(buffer.ydisp, 0); + assert.equal(buffer.lines.length, INIT_ROWS + 10); + }); + }); + + describe('filled buffer', () => { + it('should show more of the buffer above', () => { + buffer.fillViewportRows(); + // Create 10 extra blank lines + for (let i = 0; i < 10; i++) { + buffer.lines.push(terminal.blankLine()); + } + // Set cursor to the bottom of the buffer + buffer.y = INIT_ROWS - 1; + // Scroll down 10 lines + buffer.ybase = 10; + buffer.ydisp = 10; + assert.equal(buffer.lines.length, INIT_ROWS + 10); + buffer.resize(INIT_COLS, INIT_ROWS + 5); + // Should be should 5 more lines + assert.equal(buffer.ydisp, 5); + assert.equal(buffer.ybase, 5); + // Should not trim the buffer + assert.equal(buffer.lines.length, INIT_ROWS + 10); + }); + + it('should show more of the buffer below when the viewport is at the top of the buffer', () => { + buffer.fillViewportRows(); + // Create 10 extra blank lines + for (let i = 0; i < 10; i++) { + buffer.lines.push(terminal.blankLine()); + } + // Set cursor to the bottom of the buffer + buffer.y = INIT_ROWS - 1; + // Scroll down 10 lines + buffer.ybase = 10; + buffer.ydisp = 0; + assert.equal(buffer.lines.length, INIT_ROWS + 10); + buffer.resize(INIT_COLS, INIT_ROWS + 5); + // The viewport should remain at the top + assert.equal(buffer.ydisp, 0); + // The buffer ybase should move up 5 lines + assert.equal(buffer.ybase, 5); + // Should not trim the buffer + assert.equal(buffer.lines.length, INIT_ROWS + 10); + }); + }); + }); + + describe('row and column increased', () => { + it('should resize properly', () => { + buffer.fillViewportRows(); + buffer.resize(INIT_COLS + 5, INIT_ROWS + 5); + assert.equal(buffer.lines.length, INIT_ROWS + 5); + for (let i = 0; i < INIT_ROWS + 5; i++) { + assert.equal(buffer.lines.get(i).length, INIT_COLS + 5); + } + }); + }); + }); + + describe('buffer marked to have no scrollback', () => { + it('should always have a scrollback of 0', () => { + assert.equal(terminal.options.scrollback, 1000); + // Test size on initialization + buffer = new Buffer(terminal, false); + buffer.fillViewportRows(); + assert.equal(buffer.lines.maxLength, INIT_ROWS); + // Test size on buffer increase + buffer.resize(INIT_COLS, INIT_ROWS * 2); + assert.equal(buffer.lines.maxLength, INIT_ROWS * 2); + // Test size on buffer decrease + buffer.resize(INIT_COLS, INIT_ROWS / 2); + assert.equal(buffer.lines.maxLength, INIT_ROWS / 2); + }); + }); +}); diff --git a/xterm.js/src/Buffer.ts b/xterm.js/src/Buffer.ts new file mode 100644 index 0000000..623c385 --- /dev/null +++ b/xterm.js/src/Buffer.ts @@ -0,0 +1,312 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ITerminal, IBuffer } from './Interfaces'; +import { CircularList } from './utils/CircularList'; +import { LineData, CharData } from './Types'; + +export const CHAR_DATA_ATTR_INDEX = 0; +export const CHAR_DATA_CHAR_INDEX = 1; +export const CHAR_DATA_WIDTH_INDEX = 2; +export const CHAR_DATA_CODE_INDEX = 3; +export const MAX_BUFFER_SIZE = 4294967295; // 2^32 - 1 + +/** + * This class represents a terminal buffer (an internal state of the terminal), where the + * following information is stored (in high-level): + * - text content of this particular buffer + * - cursor position + * - scroll position + */ +export class Buffer implements IBuffer { + private _lines: CircularList; + + public ydisp: number; + public ybase: number; + public y: number; + public x: number; + public scrollBottom: number; + public scrollTop: number; + public tabs: any; + public savedY: number; + public savedX: number; + + /** + * Create a new Buffer. + * @param _terminal The terminal the Buffer will belong to. + * @param _hasScrollback Whether the buffer should respect the scrollback of + * the terminal. + */ + constructor( + private _terminal: ITerminal, + private _hasScrollback: boolean + ) { + this.clear(); + } + + public get lines(): CircularList { + return this._lines; + } + + public get hasScrollback(): boolean { + return this._hasScrollback && this.lines.maxLength > this._terminal.rows; + } + + public get isCursorInViewport(): boolean { + const absoluteY = this.ybase + this.y; + const relativeY = absoluteY - this.ydisp; + return (relativeY >= 0 && relativeY < this._terminal.rows); + } + + /** + * Gets the correct buffer length based on the rows provided, the terminal's + * scrollback and whether this buffer is flagged to have scrollback or not. + * @param rows The terminal rows to use in the calculation. + */ + private _getCorrectBufferLength(rows: number): number { + if (!this._hasScrollback) { + return rows; + } + + const correctBufferLength = rows + this._terminal.options.scrollback; + + return correctBufferLength > MAX_BUFFER_SIZE ? MAX_BUFFER_SIZE : correctBufferLength; + } + + /** + * Fills the buffer's viewport with blank lines. + */ + public fillViewportRows(): void { + if (this._lines.length === 0) { + let i = this._terminal.rows; + while (i--) { + this.lines.push(this._terminal.blankLine()); + } + } + } + + /** + * Clears the buffer to it's initial state, discarding all previous data. + */ + public clear(): void { + this.ydisp = 0; + this.ybase = 0; + this.y = 0; + this.x = 0; + this._lines = new CircularList(this._getCorrectBufferLength(this._terminal.rows)); + this.scrollTop = 0; + this.scrollBottom = this._terminal.rows - 1; + this.setupTabStops(); + } + + /** + * Resizes the buffer, adjusting its data accordingly. + * @param newCols The new number of columns. + * @param newRows The new number of rows. + */ + public resize(newCols: number, newRows: number): void { + // Increase max length if needed before adjustments to allow space to fill + // as required. + const newMaxLength = this._getCorrectBufferLength(newRows); + if (newMaxLength > this._lines.maxLength) { + this._lines.maxLength = newMaxLength; + } + + // The following adjustments should only happen if the buffer has been + // initialized/filled. + if (this._lines.length > 0) { + // Deal with columns increasing (we don't do anything when columns reduce) + if (this._terminal.cols < newCols) { + const ch: CharData = [this._terminal.defAttr, ' ', 1, 32]; // does xterm use the default attr? + for (let i = 0; i < this._lines.length; i++) { + // TODO: This should be removed, with tests setup for the case that was + // causing the underlying bug, see https://github.com/sourcelair/xterm.js/issues/824 + if (this._lines.get(i) === undefined) { + this._lines.set(i, this._terminal.blankLine(undefined, undefined, newCols)); + } + while (this._lines.get(i).length < newCols) { + this._lines.get(i).push(ch); + } + } + } + + // Resize rows in both directions as needed + let addToY = 0; + if (this._terminal.rows < newRows) { + for (let y = this._terminal.rows; y < newRows; y++) { + if (this._lines.length < newRows + this.ybase) { + if (this.ybase > 0 && this._lines.length <= this.ybase + this.y + addToY + 1) { + // There is room above the buffer and there are no empty elements below the line, + // scroll up + this.ybase--; + addToY++; + if (this.ydisp > 0) { + // Viewport is at the top of the buffer, must increase downwards + this.ydisp--; + } + } else { + // Add a blank line if there is no buffer left at the top to scroll to, or if there + // are blank lines after the cursor + this._lines.push(this._terminal.blankLine(undefined, undefined, newCols)); + } + } + } + } else { // (this._terminal.rows >= newRows) + for (let y = this._terminal.rows; y > newRows; y--) { + if (this._lines.length > newRows + this.ybase) { + if (this._lines.length > this.ybase + this.y + 1) { + // The line is a blank line below the cursor, remove it + this._lines.pop(); + } else { + // The line is the cursor, scroll down + this.ybase++; + this.ydisp++; + } + } + } + } + + // Reduce max length if needed after adjustments, this is done after as it + // would otherwise cut data from the bottom of the buffer. + if (newMaxLength < this._lines.maxLength) { + // Trim from the top of the buffer and adjust ybase and ydisp. + const amountToTrim = this._lines.length - newMaxLength; + if (amountToTrim > 0) { + this._lines.trimStart(amountToTrim); + this.ybase = Math.max(this.ybase - amountToTrim, 0); + this.ydisp = Math.max(this.ydisp - amountToTrim, 0); + } + this._lines.maxLength = newMaxLength; + } + + // Make sure that the cursor stays on screen + if (this.y >= newRows) { + this.y = newRows - 1; + } + if (addToY) { + this.y += addToY; + } + + if (this.x >= newCols) { + this.x = newCols - 1; + } + + this.scrollTop = 0; + } + + this.scrollBottom = newRows - 1; + } + + /** + * Translates a buffer line to a string, with optional start and end columns. + * Wide characters will count as two columns in the resulting string. This + * function is useful for getting the actual text underneath the raw selection + * position. + * @param line The line being translated. + * @param trimRight Whether to trim whitespace to the right. + * @param startCol The column to start at. + * @param endCol The column to end at. + */ + public translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol: number = 0, endCol: number = null): string { + // Get full line + let lineString = ''; + const line = this.lines.get(lineIndex); + if (!line) { + return ''; + } + + // Initialize column and index values. Column values represent the actual + // cell column, indexes represent the index in the string. Indexes are + // needed here because some chars are 0 characters long (eg. after wide + // chars) and some chars are longer than 1 characters long (eg. emojis). + let startIndex = startCol; + endCol = endCol || line.length; + let endIndex = endCol; + + for (let i = 0; i < line.length; i++) { + const char = line[i]; + lineString += char[CHAR_DATA_CHAR_INDEX]; + // Adjust start and end cols for wide characters if they affect their + // column indexes + if (char[CHAR_DATA_WIDTH_INDEX] === 0) { + if (startCol >= i) { + startIndex--; + } + if (endCol >= i) { + endIndex--; + } + } else { + // Adjust the columns to take glyphs that are represented by multiple + // code points into account. + if (char[CHAR_DATA_CHAR_INDEX].length > 1) { + if (startCol > i) { + startIndex += char[CHAR_DATA_CHAR_INDEX].length - 1; + } + if (endCol > i) { + endIndex += char[CHAR_DATA_CHAR_INDEX].length - 1; + } + } + } + } + + // Calculate the final end col by trimming whitespace on the right of the + // line if needed. + if (trimRight) { + const rightWhitespaceIndex = lineString.search(/\s+$/); + if (rightWhitespaceIndex !== -1) { + endIndex = Math.min(endIndex, rightWhitespaceIndex); + } + // Return the empty string if only trimmed whitespace is selected + if (endIndex <= startIndex) { + return ''; + } + } + + return lineString.substring(startIndex, endIndex); + } + + /** + * Setup the tab stops. + * @param i The index to start setting up tab stops from. + */ + public setupTabStops(i?: number): void { + if (i != null) { + if (!this.tabs[i]) { + i = this.prevStop(i); + } + } else { + this.tabs = {}; + i = 0; + } + + for (; i < this._terminal.cols; i += this._terminal.options.tabStopWidth) { + this.tabs[i] = true; + } + } + + /** + * Move the cursor to the previous tab stop from the given position (default is current). + * @param x The position to move the cursor to the previous tab stop. + */ + public prevStop(x?: number): number { + if (x == null) { + x = this.x; + } + while (!this.tabs[--x] && x > 0); + return x >= this._terminal.cols ? this._terminal.cols - 1 : x < 0 ? 0 : x; + } + + /** + * Move the cursor one tab stop forward from the given position (default is current). + * @param x The position to move the cursor one tab stop forward. + */ + public nextStop(x?: number): number { + if (x == null) { + x = this.x; + } + while (!this.tabs[++x] && x < this._terminal.cols); + return x >= this._terminal.cols ? this._terminal.cols - 1 : x < 0 ? 0 : x; + } +} diff --git a/xterm.js/src/BufferSet.test.ts b/xterm.js/src/BufferSet.test.ts new file mode 100644 index 0000000..b9c1824 --- /dev/null +++ b/xterm.js/src/BufferSet.test.ts @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert } from 'chai'; +import { ITerminal } from './Interfaces'; +import { BufferSet } from './BufferSet'; +import { Buffer } from './Buffer'; +import { MockTerminal } from './utils/TestUtils.test'; + +describe('BufferSet', () => { + let terminal: ITerminal; + let bufferSet: BufferSet; + + beforeEach(() => { + terminal = new MockTerminal(); + terminal.cols = 80; + terminal.rows = 24; + terminal.options.scrollback = 1000; + bufferSet = new BufferSet(terminal); + }); + + describe('constructor', () => { + it('should create two different buffers: alt and normal', () => { + assert.instanceOf(bufferSet.normal, Buffer); + assert.instanceOf(bufferSet.alt, Buffer); + assert.notEqual(bufferSet.normal, bufferSet.alt); + }); + }); + + describe('activateNormalBuffer', () => { + beforeEach(() => { + bufferSet.activateNormalBuffer(); + }); + + it('should set the normal buffer as the currently active buffer', () => { + assert.equal(bufferSet.active, bufferSet.normal); + }); + }); + + describe('activateAltBuffer', () => { + beforeEach(() => { + bufferSet.activateAltBuffer(); + }); + + it('should set the alt buffer as the currently active buffer', () => { + assert.equal(bufferSet.active, bufferSet.alt); + }); + }); +}); diff --git a/xterm.js/src/BufferSet.ts b/xterm.js/src/BufferSet.ts new file mode 100644 index 0000000..e31d227 --- /dev/null +++ b/xterm.js/src/BufferSet.ts @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ITerminal, IBufferSet } from './Interfaces'; +import { Buffer } from './Buffer'; +import { EventEmitter } from './EventEmitter'; + +/** + * The BufferSet represents the set of two buffers used by xterm terminals (normal and alt) and + * provides also utilities for working with them. + */ +export class BufferSet extends EventEmitter implements IBufferSet { + private _normal: Buffer; + private _alt: Buffer; + private _activeBuffer: Buffer; + + /** + * Create a new BufferSet for the given terminal. + * @param {Terminal} terminal - The terminal the BufferSet will belong to + */ + constructor(private _terminal: ITerminal) { + super(); + this._normal = new Buffer(this._terminal, true); + this._normal.fillViewportRows(); + + // The alt buffer should never have scrollback. + // See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer + this._alt = new Buffer(this._terminal, false); + this._activeBuffer = this._normal; + + this.setupTabStops(); + } + + /** + * Returns the alt Buffer of the BufferSet + * @returns {Buffer} + */ + public get alt(): Buffer { + return this._alt; + } + + /** + * Returns the normal Buffer of the BufferSet + * @returns {Buffer} + */ + public get active(): Buffer { + return this._activeBuffer; + } + + /** + * Returns the currently active Buffer of the BufferSet + * @returns {Buffer} + */ + public get normal(): Buffer { + return this._normal; + } + + /** + * Sets the normal Buffer of the BufferSet as its currently active Buffer + */ + public activateNormalBuffer(): void { + // The alt buffer should always be cleared when we switch to the normal + // buffer. This frees up memory since the alt buffer should always be new + // when activated. + this._alt.clear(); + + this._activeBuffer = this._normal; + this.emit('activate', this._normal); + } + + /** + * Sets the alt Buffer of the BufferSet as its currently active Buffer + */ + public activateAltBuffer(): void { + // Since the alt buffer is always cleared when the normal buffer is + // activated, we want to fill it when switching to it. + this._alt.fillViewportRows(); + this._activeBuffer = this._alt; + this.emit('activate', this._alt); + } + + /** + * Resizes both normal and alt buffers, adjusting their data accordingly. + * @param newCols The new number of columns. + * @param newRows The new number of rows. + */ + public resize(newCols: number, newRows: number): void { + this._normal.resize(newCols, newRows); + this._alt.resize(newCols, newRows); + } + + /** + * Setup the tab stops. + * @param i The index to start setting up tab stops from. + */ + public setupTabStops(i?: number): void { + this._normal.setupTabStops(i); + this._alt.setupTabStops(i); + } +} diff --git a/xterm.js/src/CharWidth.ts b/xterm.js/src/CharWidth.ts new file mode 100644 index 0000000..d296b43 --- /dev/null +++ b/xterm.js/src/CharWidth.ts @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +export const wcwidth = (function(opts: {nul: number, control: number}): (ucs: number) => number { + // extracted from https://www.cl.cam.ac.uk/%7Emgk25/ucs/wcwidth.c + // combining characters + const COMBINING_BMP = [ + [0x0300, 0x036F], [0x0483, 0x0486], [0x0488, 0x0489], + [0x0591, 0x05BD], [0x05BF, 0x05BF], [0x05C1, 0x05C2], + [0x05C4, 0x05C5], [0x05C7, 0x05C7], [0x0600, 0x0603], + [0x0610, 0x0615], [0x064B, 0x065E], [0x0670, 0x0670], + [0x06D6, 0x06E4], [0x06E7, 0x06E8], [0x06EA, 0x06ED], + [0x070F, 0x070F], [0x0711, 0x0711], [0x0730, 0x074A], + [0x07A6, 0x07B0], [0x07EB, 0x07F3], [0x0901, 0x0902], + [0x093C, 0x093C], [0x0941, 0x0948], [0x094D, 0x094D], + [0x0951, 0x0954], [0x0962, 0x0963], [0x0981, 0x0981], + [0x09BC, 0x09BC], [0x09C1, 0x09C4], [0x09CD, 0x09CD], + [0x09E2, 0x09E3], [0x0A01, 0x0A02], [0x0A3C, 0x0A3C], + [0x0A41, 0x0A42], [0x0A47, 0x0A48], [0x0A4B, 0x0A4D], + [0x0A70, 0x0A71], [0x0A81, 0x0A82], [0x0ABC, 0x0ABC], + [0x0AC1, 0x0AC5], [0x0AC7, 0x0AC8], [0x0ACD, 0x0ACD], + [0x0AE2, 0x0AE3], [0x0B01, 0x0B01], [0x0B3C, 0x0B3C], + [0x0B3F, 0x0B3F], [0x0B41, 0x0B43], [0x0B4D, 0x0B4D], + [0x0B56, 0x0B56], [0x0B82, 0x0B82], [0x0BC0, 0x0BC0], + [0x0BCD, 0x0BCD], [0x0C3E, 0x0C40], [0x0C46, 0x0C48], + [0x0C4A, 0x0C4D], [0x0C55, 0x0C56], [0x0CBC, 0x0CBC], + [0x0CBF, 0x0CBF], [0x0CC6, 0x0CC6], [0x0CCC, 0x0CCD], + [0x0CE2, 0x0CE3], [0x0D41, 0x0D43], [0x0D4D, 0x0D4D], + [0x0DCA, 0x0DCA], [0x0DD2, 0x0DD4], [0x0DD6, 0x0DD6], + [0x0E31, 0x0E31], [0x0E34, 0x0E3A], [0x0E47, 0x0E4E], + [0x0EB1, 0x0EB1], [0x0EB4, 0x0EB9], [0x0EBB, 0x0EBC], + [0x0EC8, 0x0ECD], [0x0F18, 0x0F19], [0x0F35, 0x0F35], + [0x0F37, 0x0F37], [0x0F39, 0x0F39], [0x0F71, 0x0F7E], + [0x0F80, 0x0F84], [0x0F86, 0x0F87], [0x0F90, 0x0F97], + [0x0F99, 0x0FBC], [0x0FC6, 0x0FC6], [0x102D, 0x1030], + [0x1032, 0x1032], [0x1036, 0x1037], [0x1039, 0x1039], + [0x1058, 0x1059], [0x1160, 0x11FF], [0x135F, 0x135F], + [0x1712, 0x1714], [0x1732, 0x1734], [0x1752, 0x1753], + [0x1772, 0x1773], [0x17B4, 0x17B5], [0x17B7, 0x17BD], + [0x17C6, 0x17C6], [0x17C9, 0x17D3], [0x17DD, 0x17DD], + [0x180B, 0x180D], [0x18A9, 0x18A9], [0x1920, 0x1922], + [0x1927, 0x1928], [0x1932, 0x1932], [0x1939, 0x193B], + [0x1A17, 0x1A18], [0x1B00, 0x1B03], [0x1B34, 0x1B34], + [0x1B36, 0x1B3A], [0x1B3C, 0x1B3C], [0x1B42, 0x1B42], + [0x1B6B, 0x1B73], [0x1DC0, 0x1DCA], [0x1DFE, 0x1DFF], + [0x200B, 0x200F], [0x202A, 0x202E], [0x2060, 0x2063], + [0x206A, 0x206F], [0x20D0, 0x20EF], [0x302A, 0x302F], + [0x3099, 0x309A], [0xA806, 0xA806], [0xA80B, 0xA80B], + [0xA825, 0xA826], [0xFB1E, 0xFB1E], [0xFE00, 0xFE0F], + [0xFE20, 0xFE23], [0xFEFF, 0xFEFF], [0xFFF9, 0xFFFB], + ]; + const COMBINING_HIGH = [ + [0x10A01, 0x10A03], [0x10A05, 0x10A06], [0x10A0C, 0x10A0F], + [0x10A38, 0x10A3A], [0x10A3F, 0x10A3F], [0x1D167, 0x1D169], + [0x1D173, 0x1D182], [0x1D185, 0x1D18B], [0x1D1AA, 0x1D1AD], + [0x1D242, 0x1D244], [0xE0001, 0xE0001], [0xE0020, 0xE007F], + [0xE0100, 0xE01EF] + ]; + // binary search + function bisearch(ucs: number, data: number[][]): boolean { + let min = 0; + let max = data.length - 1; + let mid; + if (ucs < data[0][0] || ucs > data[max][1]) + return false; + while (max >= min) { + mid = (min + max) >> 1; + if (ucs > data[mid][1]) + min = mid + 1; + else if (ucs < data[mid][0]) + max = mid - 1; + else + return true; + } + return false; + } + function wcwidthBMP(ucs: number): number { + // test for 8-bit control characters + if (ucs === 0) + return opts.nul; + if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) + return opts.control; + // binary search in table of non-spacing characters + if (bisearch(ucs, COMBINING_BMP)) + return 0; + // if we arrive here, ucs is not a combining or C0/C1 control character + if (isWideBMP(ucs)) { + return 2; + } + return 1; + } + function isWideBMP(ucs: number): boolean { + return ( + ucs >= 0x1100 && ( + ucs <= 0x115f || // Hangul Jamo init. consonants + ucs === 0x2329 || + ucs === 0x232a || + (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs !== 0x303f) || // CJK..Yi + (ucs >= 0xac00 && ucs <= 0xd7a3) || // Hangul Syllables + (ucs >= 0xf900 && ucs <= 0xfaff) || // CJK Compat Ideographs + (ucs >= 0xfe10 && ucs <= 0xfe19) || // Vertical forms + (ucs >= 0xfe30 && ucs <= 0xfe6f) || // CJK Compat Forms + (ucs >= 0xff00 && ucs <= 0xff60) || // Fullwidth Forms + (ucs >= 0xffe0 && ucs <= 0xffe6))); + } + function wcwidthHigh(ucs: number): 0 | 1 | 2 { + if (bisearch(ucs, COMBINING_HIGH)) + return 0; + if ((ucs >= 0x20000 && ucs <= 0x2fffd) || (ucs >= 0x30000 && ucs <= 0x3fffd)) { + return 2; + } + return 1; + } + const control = opts.control | 0; + let table: number[] | Uint32Array = null; + function init_table(): number[] | Uint32Array { + // lookup table for BMP + const CODEPOINTS = 65536; // BMP holds 65536 codepoints + const BITWIDTH = 2; // a codepoint can have a width of 0, 1 or 2 + const ITEMSIZE = 32; // using uint32_t + const CONTAINERSIZE = CODEPOINTS * BITWIDTH / ITEMSIZE; + const CODEPOINTS_PER_ITEM = ITEMSIZE / BITWIDTH; + table = (typeof Uint32Array === 'undefined') + ? new Array(CONTAINERSIZE) + : new Uint32Array(CONTAINERSIZE); + for (let i = 0; i < CONTAINERSIZE; ++i) { + let num = 0; + let pos = CODEPOINTS_PER_ITEM; + while (pos--) + num = (num << 2) | wcwidthBMP(CODEPOINTS_PER_ITEM * i + pos); + table[i] = num; + } + return table; + } + // get width from lookup table + // position in container : num / CODEPOINTS_PER_ITEM + // ==> n = table[Math.floor(num / 16)] + // ==> n = table[num >> 4] + // 16 codepoints per number: FFEEDDCCBBAA99887766554433221100 + // position in number : (num % CODEPOINTS_PER_ITEM) * BITWIDTH + // ==> m = (n % 16) * 2 + // ==> m = (num & 15) << 1 + // right shift to position m + // ==> n = n >> m e.g. m=12 000000000000FFEEDDCCBBAA99887766 + // we are only interested in 2 LSBs, cut off higher bits + // ==> n = n & 3 e.g. 000000000000000000000000000000XX + return function (num: number): number { + num = num | 0; // get asm.js like optimization under V8 + if (num < 32) + return control | 0; + if (num < 127) + return 1; + let t = table || init_table(); + if (num < 65536) + return t[num >> 4] >> ((num & 15) << 1) & 3; + // do a full search for high codepoints + return wcwidthHigh(num); + }; +})({nul: 0, control: 0}); // configurable options diff --git a/xterm.js/src/Charsets.ts b/xterm.js/src/Charsets.ts new file mode 100644 index 0000000..0ee91d3 --- /dev/null +++ b/xterm.js/src/Charsets.ts @@ -0,0 +1,255 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { Charset } from './Types'; + +/** + * The character sets supported by the terminal. These enable several languages + * to be represented within the terminal with only 8-bit encoding. See ISO 2022 + * for a discussion on character sets. Only VT100 character sets are supported. + */ +export const CHARSETS: { [key: string]: Charset } = {}; + +/** + * The default character set, US. + */ +export const DEFAULT_CHARSET: Charset = CHARSETS['B']; + +/** + * DEC Special Character and Line Drawing Set. + * Reference: http://vt100.net/docs/vt102-ug/table5-13.html + * A lot of curses apps use this if they see TERM=xterm. + * testing: echo -e '\e(0a\e(B' + * The xterm output sometimes seems to conflict with the + * reference above. xterm seems in line with the reference + * when running vttest however. + * The table below now uses xterm's output from vttest. + */ +CHARSETS['0'] = { + '`': '\u25c6', // '◆' + 'a': '\u2592', // '▒' + 'b': '\u0009', // '\t' + 'c': '\u000c', // '\f' + 'd': '\u000d', // '\r' + 'e': '\u000a', // '\n' + 'f': '\u00b0', // '°' + 'g': '\u00b1', // '±' + 'h': '\u2424', // '\u2424' (NL) + 'i': '\u000b', // '\v' + 'j': '\u2518', // '┘' + 'k': '\u2510', // '┐' + 'l': '\u250c', // '┌' + 'm': '\u2514', // '└' + 'n': '\u253c', // '┼' + 'o': '\u23ba', // '⎺' + 'p': '\u23bb', // '⎻' + 'q': '\u2500', // '─' + 'r': '\u23bc', // '⎼' + 's': '\u23bd', // '⎽' + 't': '\u251c', // '├' + 'u': '\u2524', // '┤' + 'v': '\u2534', // '┴' + 'w': '\u252c', // '┬' + 'x': '\u2502', // '│' + 'y': '\u2264', // '≤' + 'z': '\u2265', // '≥' + '{': '\u03c0', // 'π' + '|': '\u2260', // '≠' + '}': '\u00a3', // '£' + '~': '\u00b7' // '·' +}; + +/** + * British character set + * ESC (A + * Reference: http://vt100.net/docs/vt220-rm/table2-5.html + */ +CHARSETS['A'] = { + '#': '£' +}; + +/** + * United States character set + * ESC (B + */ +CHARSETS['B'] = null; + +/** + * Dutch character set + * ESC (4 + * Reference: http://vt100.net/docs/vt220-rm/table2-6.html + */ +CHARSETS['4'] = { + '#': '£', + '@': '¾', + '[': 'ij', + '\\': '½', + ']': '|', + '{': '¨', + '|': 'f', + '}': '¼', + '~': '´' +}; + +/** + * Finnish character set + * ESC (C or ESC (5 + * Reference: http://vt100.net/docs/vt220-rm/table2-7.html + */ +CHARSETS['C'] = +CHARSETS['5'] = { + '[': 'Ä', + '\\': 'Ö', + ']': 'Å', + '^': 'Ü', + '`': 'é', + '{': 'ä', + '|': 'ö', + '}': 'å', + '~': 'ü' +}; + +/** + * French character set + * ESC (R + * Reference: http://vt100.net/docs/vt220-rm/table2-8.html + */ +CHARSETS['R'] = { + '#': '£', + '@': 'à', + '[': '°', + '\\': 'ç', + ']': '§', + '{': 'é', + '|': 'ù', + '}': 'è', + '~': '¨' +}; + +/** + * French Canadian character set + * ESC (Q + * Reference: http://vt100.net/docs/vt220-rm/table2-9.html + */ +CHARSETS['Q'] = { + '@': 'à', + '[': 'â', + '\\': 'ç', + ']': 'ê', + '^': 'î', + '`': 'ô', + '{': 'é', + '|': 'ù', + '}': 'è', + '~': 'û' +}; + +/** + * German character set + * ESC (K + * Reference: http://vt100.net/docs/vt220-rm/table2-10.html + */ +CHARSETS['K'] = { + '@': '§', + '[': 'Ä', + '\\': 'Ö', + ']': 'Ü', + '{': 'ä', + '|': 'ö', + '}': 'ü', + '~': 'ß' +}; + +/** + * Italian character set + * ESC (Y + * Reference: http://vt100.net/docs/vt220-rm/table2-11.html + */ +CHARSETS['Y'] = { + '#': '£', + '@': '§', + '[': '°', + '\\': 'ç', + ']': 'é', + '`': 'ù', + '{': 'à', + '|': 'ò', + '}': 'è', + '~': 'ì' +}; + +/** + * Norwegian/Danish character set + * ESC (E or ESC (6 + * Reference: http://vt100.net/docs/vt220-rm/table2-12.html + */ +CHARSETS['E'] = +CHARSETS['6'] = { + '@': 'Ä', + '[': 'Æ', + '\\': 'Ø', + ']': 'Å', + '^': 'Ü', + '`': 'ä', + '{': 'æ', + '|': 'ø', + '}': 'å', + '~': 'ü' +}; + +/** + * Spanish character set + * ESC (Z + * Reference: http://vt100.net/docs/vt220-rm/table2-13.html + */ +CHARSETS['Z'] = { + '#': '£', + '@': '§', + '[': '¡', + '\\': 'Ñ', + ']': '¿', + '{': '°', + '|': 'ñ', + '}': 'ç' +}; + +/** + * Swedish character set + * ESC (H or ESC (7 + * Reference: http://vt100.net/docs/vt220-rm/table2-14.html + */ +CHARSETS['H'] = +CHARSETS['7'] = { + '@': 'É', + '[': 'Ä', + '\\': 'Ö', + ']': 'Å', + '^': 'Ü', + '`': 'é', + '{': 'ä', + '|': 'ö', + '}': 'å', + '~': 'ü' +}; + +/** + * Swiss character set + * ESC (= + * Reference: http://vt100.net/docs/vt220-rm/table2-15.html + */ +CHARSETS['='] = { + '#': 'ù', + '@': 'à', + '[': 'é', + '\\': 'ç', + ']': 'ê', + '^': 'î', + '_': 'è', + '`': 'ô', + '{': 'ä', + '|': 'ö', + '}': 'ü', + '~': 'û' +}; diff --git a/xterm.js/src/CompositionHelper.test.ts b/xterm.js/src/CompositionHelper.test.ts new file mode 100644 index 0000000..09a59f7 --- /dev/null +++ b/xterm.js/src/CompositionHelper.test.ts @@ -0,0 +1,251 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert } from 'chai'; +import { CompositionHelper } from './CompositionHelper'; + +describe('CompositionHelper', () => { + let terminal; + let compositionHelper; + let compositionView; + let textarea; + let handledText; + + beforeEach(() => { + compositionView = { + classList: { + add: () => {}, + remove: () => {}, + }, + getBoundingClientRect: () => { + return { width: 0 }; + }, + style: { + left: 0, + top: 0 + }, + textContent: '' + }; + textarea = { + value: '', + style: { + left: 0, + top: 0 + } + }; + terminal = { + element: { + querySelector: () => { + return { offsetLeft: 0, offsetTop: 0 }; + } + }, + handler: (text: string) => { + handledText += text; + }, + buffer: { + isCursorInViewport: true + }, + charMeasure: { + height: 10, + width: 10 + }, + options: { + lineHeight: 1 + } + }; + handledText = ''; + compositionHelper = new CompositionHelper(textarea, compositionView, terminal); + }); + + describe('Input', () => { + it('Should insert simple characters', (done) => { + // First character 'ㅇ' + compositionHelper.compositionstart(); + compositionHelper.compositionupdate({ data: 'ㅇ' }); + textarea.value = 'ㅇ'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionend(); + setTimeout(() => { // wait for any textarea updates + assert.equal(handledText, 'ㅇ'); + // Second character 'ㅇ' + compositionHelper.compositionstart(); + compositionHelper.compositionupdate({ data: 'ㅇ' }); + textarea.value = 'ㅇㅇ'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionend(); + setTimeout(() => { // wait for any textarea updates + assert.equal(handledText, 'ㅇㅇ'); + done(); + }, 0); + }, 0); + }, 0); + }, 0); + }); + + it('Should insert complex characters', (done) => { + // First character '앙' + compositionHelper.compositionstart(); + compositionHelper.compositionupdate({ data: 'ㅇ' }); + textarea.value = 'ㅇ'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionupdate({ data: '아' }); + textarea.value = '아'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionupdate({ data: '앙' }); + textarea.value = '앙'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionend(); + setTimeout(() => { // wait for any textarea updates + assert.equal(handledText, '앙'); + // Second character '앙' + compositionHelper.compositionstart(); + compositionHelper.compositionupdate({ data: 'ㅇ' }); + textarea.value = '앙ㅇ'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionupdate({ data: '아' }); + textarea.value = '앙아'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionupdate({ data: '앙' }); + textarea.value = '앙앙'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionend(); + setTimeout(() => { // wait for any textarea updates + assert.equal(handledText, '앙앙'); + done(); + }, 0); + }, 0); + }, 0); + }, 0); + }, 0); + }, 0); + }, 0); + }, 0); + }); + + it('Should insert complex characters that change with following character', (done) => { + // First character '아' + compositionHelper.compositionstart(); + compositionHelper.compositionupdate({ data: 'ㅇ' }); + textarea.value = 'ㅇ'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionupdate({ data: '아' }); + textarea.value = '아'; + setTimeout(() => { // wait for any textarea updates + // Start second character '아' in first character + compositionHelper.compositionupdate({ data: '앙' }); + textarea.value = '앙'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionend(); + compositionHelper.compositionstart(); + compositionHelper.compositionupdate({ data: '아' }); + textarea.value = '아아'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionend(); + setTimeout(() => { // wait for any textarea updates + assert.equal(handledText, '아아'); + done(); + }, 0); + }, 0); + }, 0); + }, 0); + }, 0); + }); + + it('Should insert multi-characters compositions', (done) => { + // First character 'だ' + compositionHelper.compositionstart(); + compositionHelper.compositionupdate({ data: 'd' }); + textarea.value = 'd'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionupdate({ data: 'だ' }); + textarea.value = 'だ'; + setTimeout(() => { // wait for any textarea updates + // Second character 'あ' + compositionHelper.compositionupdate({ data: 'だあ' }); + textarea.value = 'だあ'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionend(); + setTimeout(() => { // wait for any textarea updates + assert.equal(handledText, 'だあ'); + done(); + }, 0); + }, 0); + }, 0); + }, 0); + }); + + it('Should insert multi-character compositions that are converted to other characters with the same length', (done) => { + // First character 'だ' + compositionHelper.compositionstart(); + compositionHelper.compositionupdate({ data: 'd' }); + textarea.value = 'd'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionupdate({ data: 'だ' }); + textarea.value = 'だ'; + setTimeout(() => { // wait for any textarea updates + // Second character 'ー' + compositionHelper.compositionupdate({ data: 'だー' }); + textarea.value = 'だー'; + setTimeout(() => { // wait for any textarea updates + // Convert to katakana 'ダー' + compositionHelper.compositionupdate({ data: 'ダー' }); + textarea.value = 'ダー'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionend(); + setTimeout(() => { // wait for any textarea updates + assert.equal(handledText, 'ダー'); + done(); + }, 0); + }, 0); + }, 0); + }, 0); + }, 0); + }); + + it('Should insert multi-character compositions that are converted to other characters with different lengths', (done) => { + // First character 'い' + compositionHelper.compositionstart(); + compositionHelper.compositionupdate({ data: 'い' }); + textarea.value = 'い'; + setTimeout(() => { // wait for any textarea updates + // Second character 'ま' + compositionHelper.compositionupdate({ data: 'いm' }); + textarea.value = 'いm'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionupdate({ data: 'いま' }); + textarea.value = 'いま'; + setTimeout(() => { // wait for any textarea updates + // Convert to kanji '今' + compositionHelper.compositionupdate({ data: '今' }); + textarea.value = '今'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionend(); + setTimeout(() => { // wait for any textarea updates + assert.equal(handledText, '今'); + done(); + }, 0); + }, 0); + }, 0); + }, 0); + }, 0); + }); + + it('Should insert non-composition characters input immediately after composition characters', (done) => { + // First character 'ㅇ' + compositionHelper.compositionstart(); + compositionHelper.compositionupdate({ data: 'ㅇ' }); + textarea.value = 'ㅇ'; + setTimeout(() => { // wait for any textarea updates + compositionHelper.compositionend(); + // Second character '1' (a non-composition character) + textarea.value = 'ㅇ1'; + setTimeout(() => { // wait for any textarea updates + assert.equal(handledText, 'ㅇ1'); + done(); + }, 0); + }, 0); + }); + }); +}); diff --git a/xterm.js/src/CompositionHelper.ts b/xterm.js/src/CompositionHelper.ts new file mode 100644 index 0000000..ca5b4f4 --- /dev/null +++ b/xterm.js/src/CompositionHelper.ts @@ -0,0 +1,230 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ITerminal } from './Interfaces'; + +interface IPosition { + start: number; + end: number; +} + +/** + * Encapsulates the logic for handling compositionstart, compositionupdate and compositionend + * events, displaying the in-progress composition to the UI and forwarding the final composition + * to the handler. + */ +export class CompositionHelper { + /** + * Whether input composition is currently happening, eg. via a mobile keyboard, speech input or + * IME. This variable determines whether the compositionText should be displayed on the UI. + */ + private isComposing: boolean; + + /** + * The position within the input textarea's value of the current composition. + */ + private compositionPosition: IPosition; + + /** + * Whether a composition is in the process of being sent, setting this to false will cancel any + * in-progress composition. + */ + private isSendingComposition: boolean; + + /** + * Creates a new CompositionHelper. + * @param textarea The textarea that xterm uses for input. + * @param compositionView The element to display the in-progress composition in. + * @param terminal The Terminal to forward the finished composition to. + */ + constructor( + private textarea: HTMLTextAreaElement, + private compositionView: HTMLElement, + private terminal: ITerminal + ) { + this.isComposing = false; + this.isSendingComposition = false; + this.compositionPosition = { start: null, end: null }; + } + + /** + * Handles the compositionstart event, activating the composition view. + */ + public compositionstart(): void { + this.isComposing = true; + this.compositionPosition.start = this.textarea.value.length; + this.compositionView.textContent = ''; + this.compositionView.classList.add('active'); + } + + /** + * Handles the compositionupdate event, updating the composition view. + * @param {CompositionEvent} ev The event. + */ + public compositionupdate(ev: CompositionEvent): void { + this.compositionView.textContent = ev.data; + this.updateCompositionElements(); + setTimeout(() => { + this.compositionPosition.end = this.textarea.value.length; + }, 0); + } + + /** + * Handles the compositionend event, hiding the composition view and sending the composition to + * the handler. + */ + public compositionend(): void { + this.finalizeComposition(true); + } + + /** + * Handles the keydown event, routing any necessary events to the CompositionHelper functions. + * @param ev The keydown event. + * @return Whether the Terminal should continue processing the keydown event. + */ + public keydown(ev: KeyboardEvent): boolean { + if (this.isComposing || this.isSendingComposition) { + if (ev.keyCode === 229) { + // Continue composing if the keyCode is the "composition character" + return false; + } else if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) { + // Continue composing if the keyCode is a modifier key + return false; + } else { + // Finish composition immediately. This is mainly here for the case where enter is + // pressed and the handler needs to be triggered before the command is executed. + this.finalizeComposition(false); + } + } + + if (ev.keyCode === 229) { + // If the "composition character" is used but gets to this point it means a non-composition + // character (eg. numbers and punctuation) was pressed when the IME was active. + this.handleAnyTextareaChanges(); + return false; + } + + return true; + } + + /** + * Finalizes the composition, resuming regular input actions. This is called when a composition + * is ending. + * @param waitForPropogation Whether to wait for events to propogate before sending + * the input. This should be false if a non-composition keystroke is entered before the + * compositionend event is triggered, such as enter, so that the composition is send before + * the command is executed. + */ + private finalizeComposition(waitForPropogation: boolean): void { + this.compositionView.classList.remove('active'); + this.isComposing = false; + this.clearTextareaPosition(); + + if (!waitForPropogation) { + // Cancel any delayed composition send requests and send the input immediately. + this.isSendingComposition = false; + const input = this.textarea.value.substring(this.compositionPosition.start, this.compositionPosition.end); + this.terminal.handler(input); + } else { + // Make a deep copy of the composition position here as a new compositionstart event may + // fire before the setTimeout executes. + const currentCompositionPosition = { + start: this.compositionPosition.start, + end: this.compositionPosition.end, + }; + + // Since composition* events happen before the changes take place in the textarea on most + // browsers, use a setTimeout with 0ms time to allow the native compositionend event to + // complete. This ensures the correct character is retrieved, this solution was used + // because: + // - The compositionend event's data property is unreliable, at least on Chromium + // - The last compositionupdate event's data property does not always accurately describe + // the character, a counter example being Korean where an ending consonsant can move to + // the following character if the following input is a vowel. + this.isSendingComposition = true; + setTimeout(() => { + // Ensure that the input has not already been sent + if (this.isSendingComposition) { + this.isSendingComposition = false; + let input; + if (this.isComposing) { + // Use the end position to get the string if a new composition has started. + input = this.textarea.value.substring(currentCompositionPosition.start, currentCompositionPosition.end); + } else { + // Don't use the end position here in order to pick up any characters after the + // composition has finished, for example when typing a non-composition character + // (eg. 2) after a composition character. + input = this.textarea.value.substring(currentCompositionPosition.start); + } + this.terminal.handler(input); + } + }, 0); + } + } + + /** + * Apply any changes made to the textarea after the current event chain is allowed to complete. + * This should be called when not currently composing but a keydown event with the "composition + * character" (229) is triggered, in order to allow non-composition text to be entered when an + * IME is active. + */ + private handleAnyTextareaChanges(): void { + const oldValue = this.textarea.value; + setTimeout(() => { + // Ignore if a composition has started since the timeout + if (!this.isComposing) { + const newValue = this.textarea.value; + const diff = newValue.replace(oldValue, ''); + if (diff.length > 0) { + this.terminal.handler(diff); + } + } + }, 0); + } + + /** + * Positions the composition view on top of the cursor and the textarea just below it (so the + * IME helper dialog is positioned correctly). + * @param dontRecurse Whether to use setTimeout to recursively trigger another update, this is + * necessary as the IME events across browsers are not consistently triggered. + */ + public updateCompositionElements(dontRecurse?: boolean): void { + if (!this.isComposing) { + return; + } + + if (this.terminal.buffer.isCursorInViewport) { + const cellHeight = Math.ceil(this.terminal.charMeasure.height * this.terminal.options.lineHeight); + const cursorTop = this.terminal.buffer.y * cellHeight; + const cursorLeft = this.terminal.buffer.x * this.terminal.charMeasure.width; + + this.compositionView.style.left = cursorLeft + 'px'; + this.compositionView.style.top = cursorTop + 'px'; + this.compositionView.style.height = cellHeight + 'px'; + this.compositionView.style.lineHeight = cellHeight + 'px'; + // Sync the textarea to the exact position of the composition view so the IME knows where the + // text is. + const compositionViewBounds = this.compositionView.getBoundingClientRect(); + this.textarea.style.left = cursorLeft + 'px'; + this.textarea.style.top = cursorTop + 'px'; + this.textarea.style.width = compositionViewBounds.width + 'px'; + this.textarea.style.height = compositionViewBounds.height + 'px'; + this.textarea.style.lineHeight = compositionViewBounds.height + 'px'; + } + + if (!dontRecurse) { + setTimeout(() => this.updateCompositionElements(true), 0); + } + }; + + /** + * Clears the textarea's position so that the cursor does not blink on IE. + * @private + */ + private clearTextareaPosition(): void { + this.textarea.style.left = ''; + this.textarea.style.top = ''; + }; +} diff --git a/xterm.js/src/EscapeSequences.ts b/xterm.js/src/EscapeSequences.ts new file mode 100644 index 0000000..cb97c36 --- /dev/null +++ b/xterm.js/src/EscapeSequences.ts @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +/** + * C0 control codes + * See = https://en.wikipedia.org/wiki/C0_and_C1_control_codes + */ +export namespace C0 { + /** Null (Caret = ^@, C = \0) */ + export const NUL = '\x00'; + /** Start of Heading (Caret = ^A) */ + export const SOH = '\x01'; + /** Start of Text (Caret = ^B) */ + export const STX = '\x02'; + /** End of Text (Caret = ^C) */ + export const ETX = '\x03'; + /** End of Transmission (Caret = ^D) */ + export const EOT = '\x04'; + /** Enquiry (Caret = ^E) */ + export const ENQ = '\x05'; + /** Acknowledge (Caret = ^F) */ + export const ACK = '\x06'; + /** Bell (Caret = ^G, C = \a) */ + export const BEL = '\x07'; + /** Backspace (Caret = ^H, C = \b) */ + export const BS = '\x08'; + /** Character Tabulation, Horizontal Tabulation (Caret = ^I, C = \t) */ + export const HT = '\x09'; + /** Line Feed (Caret = ^J, C = \n) */ + export const LF = '\x0a'; + /** Line Tabulation, Vertical Tabulation (Caret = ^K, C = \v) */ + export const VT = '\x0b'; + /** Form Feed (Caret = ^L, C = \f) */ + export const FF = '\x0c'; + /** Carriage Return (Caret = ^M, C = \r) */ + export const CR = '\x0d'; + /** Shift Out (Caret = ^N) */ + export const SO = '\x0e'; + /** Shift In (Caret = ^O) */ + export const SI = '\x0f'; + /** Data Link Escape (Caret = ^P) */ + export const DLE = '\x10'; + /** Device Control One (XON) (Caret = ^Q) */ + export const DC1 = '\x11'; + /** Device Control Two (Caret = ^R) */ + export const DC2 = '\x12'; + /** Device Control Three (XOFF) (Caret = ^S) */ + export const DC3 = '\x13'; + /** Device Control Four (Caret = ^T) */ + export const DC4 = '\x14'; + /** Negative Acknowledge (Caret = ^U) */ + export const NAK = '\x15'; + /** Synchronous Idle (Caret = ^V) */ + export const SYN = '\x16'; + /** End of Transmission Block (Caret = ^W) */ + export const ETB = '\x17'; + /** Cancel (Caret = ^X) */ + export const CAN = '\x18'; + /** End of Medium (Caret = ^Y) */ + export const EM = '\x19'; + /** Substitute (Caret = ^Z) */ + export const SUB = '\x1a'; + /** Escape (Caret = ^[, C = \e) */ + export const ESC = '\x1b'; + /** File Separator (Caret = ^\) */ + export const FS = '\x1c'; + /** Group Separator (Caret = ^]) */ + export const GS = '\x1d'; + /** Record Separator (Caret = ^^) */ + export const RS = '\x1e'; + /** Unit Separator (Caret = ^_) */ + export const US = '\x1f'; + /** Space */ + export const SP = '\x20'; + /** Delete (Caret = ^?) */ + export const DEL = '\x7f'; +}; diff --git a/xterm.js/src/EventEmitter.test.ts b/xterm.js/src/EventEmitter.test.ts new file mode 100644 index 0000000..c1f0a0a --- /dev/null +++ b/xterm.js/src/EventEmitter.test.ts @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert } from 'chai'; +import { EventEmitter } from './EventEmitter'; + +describe('EventEmitter', () => { + let eventEmitter: EventEmitter; + + beforeEach(() => { + eventEmitter = new EventEmitter(); + }); + + describe('once', () => { + it('should trigger the listener only once', () => { + let count = 0; + const listener = () => count++; + eventEmitter.once('test', listener); + eventEmitter.emit('test'); + assert.equal(count, 1); + eventEmitter.emit('test'); + assert.equal(count, 1); + }); + }); + + describe('emit', () => { + it('should emit events to listeners', () => { + let count1 = 0; + let count2 = 0; + const listener1 = () => count1++; + const listener2 = () => count2++; + eventEmitter.on('test', listener1); + eventEmitter.on('test', listener2); + eventEmitter.emit('test'); + assert.equal(count1, 1); + assert.equal(count2, 1); + eventEmitter.emit('test'); + assert.equal(count1, 2); + assert.equal(count2, 2); + }); + + it('should manage multiple listener types', () => { + let count1 = 0; + let count2 = 0; + const listener1 = () => count1++; + const listener2 = () => count2++; + eventEmitter.on('test', listener1); + eventEmitter.on('foo', listener2); + eventEmitter.emit('test'); + assert.equal(count1, 1); + assert.equal(count2, 0); + eventEmitter.emit('foo'); + assert.equal(count1, 1); + assert.equal(count2, 1); + }); + }); + + describe('listeners', () => { + it('should return listeners for the type requested', () => { + assert.equal(eventEmitter.listeners('test').length, 0); + const listener = () => {}; + eventEmitter.on('test', listener); + assert.deepEqual(eventEmitter.listeners('test'), [listener]); + }); + }); + + describe('off', () => { + it('should remove the specific listener', () => { + const listener1 = () => {}; + const listener2 = () => {}; + eventEmitter.on('foo', listener1); + eventEmitter.on('foo', listener2); + assert.equal(eventEmitter.listeners('foo').length, 2); + eventEmitter.off('foo', listener1); + assert.deepEqual(eventEmitter.listeners('foo'), [listener2]); + }); + }); + + describe('removeAllListeners', () => { + it('should clear all listeners', () => { + eventEmitter.on('foo', () => {}); + assert.equal(eventEmitter.listeners('foo').length, 1); + eventEmitter.removeAllListeners('foo'); + assert.equal(eventEmitter.listeners('foo').length, 0); + }); + }); +}); diff --git a/xterm.js/src/EventEmitter.ts b/xterm.js/src/EventEmitter.ts new file mode 100644 index 0000000..414eac8 --- /dev/null +++ b/xterm.js/src/EventEmitter.ts @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { IEventEmitter, IListenerType } from './Interfaces'; + +export class EventEmitter implements IEventEmitter { + private _events: {[type: string]: IListenerType[]}; + + constructor() { + // Restore the previous events if available, this will happen if the + // constructor is called multiple times on the same object (terminal reset). + this._events = this._events || {}; + } + + public on(type: string, listener: IListenerType): void { + this._events[type] = this._events[type] || []; + this._events[type].push(listener); + } + + public off(type: string, listener: IListenerType): void { + if (!this._events[type]) { + return; + } + + let obj = this._events[type]; + let i = obj.length; + + while (i--) { + if (obj[i] === listener || obj[i].listener === listener) { + obj.splice(i, 1); + return; + } + } + } + + public removeAllListeners(type: string): void { + if (this._events[type]) { + delete this._events[type]; + } + } + + public once(type: string, listener: IListenerType): void { + function on(): void { + let args = Array.prototype.slice.call(arguments); + this.off(type, on); + listener.apply(this, args); + } + (on).listener = listener; + this.on(type, on); + } + + public emit(type: string, ...args: any[]): void { + if (!this._events[type]) { + return; + } + let obj = this._events[type]; + for (let i = 0; i < obj.length; i++) { + obj[i].apply(this, args); + } + } + + public listeners(type: string): IListenerType[] { + return this._events[type] || []; + } + + protected destroy(): void { + this._events = {}; + } +} diff --git a/xterm.js/src/InputHandler.test.ts b/xterm.js/src/InputHandler.test.ts new file mode 100644 index 0000000..eb7b70d --- /dev/null +++ b/xterm.js/src/InputHandler.test.ts @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert } from 'chai'; +import { InputHandler } from './InputHandler'; +import { MockInputHandlingTerminal } from './utils/TestUtils.test'; + +describe('InputHandler', () => { + describe('save and restore cursor', () => { + let terminal = new MockInputHandlingTerminal(); + terminal.buffer.x = 1; + terminal.buffer.y = 2; + let inputHandler = new InputHandler(terminal); + // Save cursor position + inputHandler.saveCursor([]); + assert.equal(terminal.buffer.x, 1); + assert.equal(terminal.buffer.y, 2); + // Change cursor position + terminal.buffer.x = 10; + terminal.buffer.y = 20; + // Restore cursor position + inputHandler.restoreCursor([]); + assert.equal(terminal.buffer.x, 1); + assert.equal(terminal.buffer.y, 2); + }); + describe('setCursorStyle', () => { + it('should call Terminal.setOption with correct params', () => { + let terminal = new MockInputHandlingTerminal(); + let inputHandler = new InputHandler(terminal); + + inputHandler.setCursorStyle([0]); + assert.equal(terminal.options['cursorStyle'], 'block'); + assert.equal(terminal.options['cursorBlink'], true); + + terminal.options = {}; + inputHandler.setCursorStyle([1]); + assert.equal(terminal.options['cursorStyle'], 'block'); + assert.equal(terminal.options['cursorBlink'], true); + + terminal.options = {}; + inputHandler.setCursorStyle([2]); + assert.equal(terminal.options['cursorStyle'], 'block'); + assert.equal(terminal.options['cursorBlink'], false); + + terminal.options = {}; + inputHandler.setCursorStyle([3]); + assert.equal(terminal.options['cursorStyle'], 'underline'); + assert.equal(terminal.options['cursorBlink'], true); + + terminal.options = {}; + inputHandler.setCursorStyle([4]); + assert.equal(terminal.options['cursorStyle'], 'underline'); + assert.equal(terminal.options['cursorBlink'], false); + + terminal.options = {}; + inputHandler.setCursorStyle([5]); + assert.equal(terminal.options['cursorStyle'], 'bar'); + assert.equal(terminal.options['cursorBlink'], true); + + terminal.options = {}; + inputHandler.setCursorStyle([6]); + assert.equal(terminal.options['cursorStyle'], 'bar'); + assert.equal(terminal.options['cursorBlink'], false); + }); + }); + describe('setMode', () => { + it('should toggle Terminal.bracketedPasteMode', () => { + let terminal = new MockInputHandlingTerminal(); + terminal.prefix = '?'; + terminal.bracketedPasteMode = false; + let inputHandler = new InputHandler(terminal); + // Set bracketed paste mode + inputHandler.setMode([2004]); + assert.equal(terminal.bracketedPasteMode, true); + // Reset bracketed paste mode + inputHandler.resetMode([2004]); + assert.equal(terminal.bracketedPasteMode, false); + }); + }); +}); diff --git a/xterm.js/src/InputHandler.ts b/xterm.js/src/InputHandler.ts new file mode 100644 index 0000000..1ba6dc7 --- /dev/null +++ b/xterm.js/src/InputHandler.ts @@ -0,0 +1,1455 @@ +/** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) + * @license MIT + */ + +import { IInputHandler, ITerminal, IInputHandlingTerminal } from './Interfaces'; +import { C0 } from './EscapeSequences'; +import { DEFAULT_CHARSET } from './Charsets'; +import { CharData } from './Types'; +import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from './Buffer'; +import { FLAGS } from './renderer/Types'; +import { wcwidth } from './CharWidth'; + +/** + * The terminal's standard implementation of IInputHandler, this handles all + * input from the Parser. + * + * Refer to http://invisible-island.net/xterm/ctlseqs/ctlseqs.html to understand + * each function's header comment. + */ +export class InputHandler implements IInputHandler { + constructor(private _terminal: IInputHandlingTerminal) { } + + public addChar(char: string, code: number): void { + if (char >= ' ') { + // calculate print space + // expensive call, therefore we save width in line buffer + const ch_width = wcwidth(code); + + if (this._terminal.charset && this._terminal.charset[char]) { + char = this._terminal.charset[char]; + } + + let row = this._terminal.buffer.y + this._terminal.buffer.ybase; + + // insert combining char in last cell + // FIXME: needs handling after cursor jumps + if (!ch_width && this._terminal.buffer.x) { + // dont overflow left + if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1]) { + if (!this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][CHAR_DATA_WIDTH_INDEX]) { + // found empty cell after fullwidth, need to go 2 cells back + if (this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2]) { + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2][CHAR_DATA_CHAR_INDEX] += char; + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 2][3] = char.charCodeAt(0); + } + } else { + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][CHAR_DATA_CHAR_INDEX] += char; + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x - 1][3] = char.charCodeAt(0); + } + this._terminal.updateRange(this._terminal.buffer.y); + } + return; + } + + // goto next line if ch would overflow + // TODO: needs a global min terminal width of 2 + if (this._terminal.buffer.x + ch_width - 1 >= this._terminal.cols) { + // autowrap - DECAWM + if (this._terminal.wraparoundMode) { + this._terminal.buffer.x = 0; + this._terminal.buffer.y++; + if (this._terminal.buffer.y > this._terminal.buffer.scrollBottom) { + this._terminal.buffer.y--; + this._terminal.scroll(true); + } else { + // The line already exists (eg. the initial viewport), mark it as a + // wrapped line + (this._terminal.buffer.lines.get(this._terminal.buffer.y)).isWrapped = true; + } + } else { + if (ch_width === 2) // FIXME: check for xterm behavior + return; + } + } + row = this._terminal.buffer.y + this._terminal.buffer.ybase; + + // insert mode: move characters to right + if (this._terminal.insertMode) { + // do this twice for a fullwidth char + for (let moves = 0; moves < ch_width; ++moves) { + // remove last cell, if it's width is 0 + // we have to adjust the second last cell as well + const removed = this._terminal.buffer.lines.get(this._terminal.buffer.y + this._terminal.buffer.ybase).pop(); + if (removed[CHAR_DATA_WIDTH_INDEX] === 0 + && this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] + && this._terminal.buffer.lines.get(row)[this._terminal.cols - 2][CHAR_DATA_WIDTH_INDEX] === 2) { + this._terminal.buffer.lines.get(row)[this._terminal.cols - 2] = [this._terminal.curAttr, ' ', 1, ' '.charCodeAt(0)]; + } + + // insert empty cell at cursor + this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 0, [this._terminal.curAttr, ' ', 1, ' '.charCodeAt(0)]); + } + } + + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, char, ch_width, char.charCodeAt(0)]; + this._terminal.buffer.x++; + this._terminal.updateRange(this._terminal.buffer.y); + + // fullwidth char - set next cell width to zero and advance cursor + if (ch_width === 2) { + this._terminal.buffer.lines.get(row)[this._terminal.buffer.x] = [this._terminal.curAttr, '', 0, undefined]; + this._terminal.buffer.x++; + } + } + } + + /** + * BEL + * Bell (Ctrl-G). + */ + public bell(): void { + this._terminal.bell(); + } + + /** + * LF + * Line Feed or New Line (NL). (LF is Ctrl-J). + */ + public lineFeed(): void { + if (this._terminal.convertEol) { + this._terminal.buffer.x = 0; + } + this._terminal.buffer.y++; + if (this._terminal.buffer.y > this._terminal.buffer.scrollBottom) { + this._terminal.buffer.y--; + this._terminal.scroll(); + } + // If the end of the line is hit, prevent this action from wrapping around to the next line. + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x--; + } + /** + * This event is emitted whenever the terminal outputs a LF or NL. + * + * @event linefeed + */ + this._terminal.emit('linefeed'); + } + + /** + * CR + * Carriage Return (Ctrl-M). + */ + public carriageReturn(): void { + this._terminal.buffer.x = 0; + } + + /** + * BS + * Backspace (Ctrl-H). + */ + public backspace(): void { + if (this._terminal.buffer.x > 0) { + this._terminal.buffer.x--; + } + } + + /** + * TAB + * Horizontal Tab (HT) (Ctrl-I). + */ + public tab(): void { + this._terminal.buffer.x = this._terminal.buffer.nextStop(); + } + + /** + * SO + * Shift Out (Ctrl-N) -> Switch to Alternate Character Set. This invokes the + * G1 character set. + */ + public shiftOut(): void { + this._terminal.setgLevel(1); + } + + /** + * SI + * Shift In (Ctrl-O) -> Switch to Standard Character Set. This invokes the G0 + * character set (the default). + */ + public shiftIn(): void { + this._terminal.setgLevel(0); + } + + /** + * CSI Ps @ + * Insert Ps (Blank) Character(s) (default = 1) (ICH). + */ + public insertChars(params: number[]): void { + let param = params[0]; + if (param < 1) param = 1; + + const row = this._terminal.buffer.y + this._terminal.buffer.ybase; + let j = this._terminal.buffer.x; + const ch: CharData = [this._terminal.eraseAttr(), ' ', 1, 32]; // xterm + + while (param-- && j < this._terminal.cols) { + this._terminal.buffer.lines.get(row).splice(j++, 0, ch); + this._terminal.buffer.lines.get(row).pop(); + } + } + + /** + * CSI Ps A + * Cursor Up Ps Times (default = 1) (CUU). + */ + public cursorUp(params: number[]): void { + let param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y -= param; + if (this._terminal.buffer.y < 0) { + this._terminal.buffer.y = 0; + } + } + + /** + * CSI Ps B + * Cursor Down Ps Times (default = 1) (CUD). + */ + public cursorDown(params: number[]): void { + let param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y += param; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + // If the end of the line is hit, prevent this action from wrapping around to the next line. + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x--; + } + } + + /** + * CSI Ps C + * Cursor Forward Ps Times (default = 1) (CUF). + */ + public cursorForward(params: number[]): void { + let param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.x += param; + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x = this._terminal.cols - 1; + } + } + + /** + * CSI Ps D + * Cursor Backward Ps Times (default = 1) (CUB). + */ + public cursorBackward(params: number[]): void { + let param = params[0]; + if (param < 1) { + param = 1; + } + // If the end of the line is hit, prevent this action from wrapping around to the next line. + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x--; + } + this._terminal.buffer.x -= param; + if (this._terminal.buffer.x < 0) { + this._terminal.buffer.x = 0; + } + } + + /** + * CSI Ps E + * Cursor Next Line Ps Times (default = 1) (CNL). + * same as CSI Ps B ? + */ + public cursorNextLine(params: number[]): void { + let param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y += param; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + this._terminal.buffer.x = 0; + } + + + /** + * CSI Ps F + * Cursor Preceding Line Ps Times (default = 1) (CNL). + * reuse CSI Ps A ? + */ + public cursorPrecedingLine(params: number[]): void { + let param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y -= param; + if (this._terminal.buffer.y < 0) { + this._terminal.buffer.y = 0; + } + this._terminal.buffer.x = 0; + } + + + /** + * CSI Ps G + * Cursor Character Absolute [column] (default = [row,1]) (CHA). + */ + public cursorCharAbsolute(params: number[]): void { + let param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.x = param - 1; + } + + /** + * CSI Ps ; Ps H + * Cursor Position [row;column] (default = [1,1]) (CUP). + */ + public cursorPosition(params: number[]): void { + let col: number; + let row: number = params[0] - 1; + + if (params.length >= 2) { + col = params[1] - 1; + } else { + col = 0; + } + + if (row < 0) { + row = 0; + } else if (row >= this._terminal.rows) { + row = this._terminal.rows - 1; + } + + if (col < 0) { + col = 0; + } else if (col >= this._terminal.cols) { + col = this._terminal.cols - 1; + } + + this._terminal.buffer.x = col; + this._terminal.buffer.y = row; + } + + /** + * CSI Ps I + * Cursor Forward Tabulation Ps tab stops (default = 1) (CHT). + */ + public cursorForwardTab(params: number[]): void { + let param = params[0] || 1; + while (param--) { + this._terminal.buffer.x = this._terminal.buffer.nextStop(); + } + } + + /** + * CSI Ps J Erase in Display (ED). + * Ps = 0 -> Erase Below (default). + * Ps = 1 -> Erase Above. + * Ps = 2 -> Erase All. + * Ps = 3 -> Erase Saved Lines (xterm). + * CSI ? Ps J + * Erase in Display (DECSED). + * Ps = 0 -> Selective Erase Below (default). + * Ps = 1 -> Selective Erase Above. + * Ps = 2 -> Selective Erase All. + */ + public eraseInDisplay(params: number[]): void { + let j; + switch (params[0]) { + case 0: + this._terminal.eraseRight(this._terminal.buffer.x, this._terminal.buffer.y); + j = this._terminal.buffer.y + 1; + for (; j < this._terminal.rows; j++) { + this._terminal.eraseLine(j); + } + break; + case 1: + this._terminal.eraseLeft(this._terminal.buffer.x, this._terminal.buffer.y); + j = this._terminal.buffer.y; + while (j--) { + this._terminal.eraseLine(j); + } + break; + case 2: + j = this._terminal.rows; + while (j--) this._terminal.eraseLine(j); + break; + case 3: + // Clear scrollback (everything not in viewport) + const scrollBackSize = this._terminal.buffer.lines.length - this._terminal.rows; + if (scrollBackSize > 0) { + this._terminal.buffer.lines.trimStart(scrollBackSize); + this._terminal.buffer.ybase = Math.max(this._terminal.buffer.ybase - scrollBackSize, 0); + this._terminal.buffer.ydisp = Math.max(this._terminal.buffer.ydisp - scrollBackSize, 0); + // Force a scroll event to refresh viewport + this._terminal.emit('scroll', 0); + } + break; + } + } + + /** + * CSI Ps K Erase in Line (EL). + * Ps = 0 -> Erase to Right (default). + * Ps = 1 -> Erase to Left. + * Ps = 2 -> Erase All. + * CSI ? Ps K + * Erase in Line (DECSEL). + * Ps = 0 -> Selective Erase to Right (default). + * Ps = 1 -> Selective Erase to Left. + * Ps = 2 -> Selective Erase All. + */ + public eraseInLine(params: number[]): void { + switch (params[0]) { + case 0: + this._terminal.eraseRight(this._terminal.buffer.x, this._terminal.buffer.y); + break; + case 1: + this._terminal.eraseLeft(this._terminal.buffer.x, this._terminal.buffer.y); + break; + case 2: + this._terminal.eraseLine(this._terminal.buffer.y); + break; + } + } + + /** + * CSI Ps L + * Insert Ps Line(s) (default = 1) (IL). + */ + public insertLines(params: number[]): void { + let param: number = params[0]; + if (param < 1) { + param = 1; + } + let row: number = this._terminal.buffer.y + this._terminal.buffer.ybase; + + let scrollBottomRowsOffset = this._terminal.rows - 1 - this._terminal.buffer.scrollBottom; + let scrollBottomAbsolute = this._terminal.rows - 1 + this._terminal.buffer.ybase - scrollBottomRowsOffset + 1; + while (param--) { + // test: echo -e '\e[44m\e[1L\e[0m' + // blankLine(true) - xterm/linux behavior + this._terminal.buffer.lines.splice(scrollBottomAbsolute - 1, 1); + this._terminal.buffer.lines.splice(row, 0, this._terminal.blankLine(true)); + } + + // this.maxRange(); + this._terminal.updateRange(this._terminal.buffer.y); + this._terminal.updateRange(this._terminal.buffer.scrollBottom); + } + + /** + * CSI Ps M + * Delete Ps Line(s) (default = 1) (DL). + */ + public deleteLines(params: number[]): void { + let param = params[0]; + if (param < 1) { + param = 1; + } + const row: number = this._terminal.buffer.y + this._terminal.buffer.ybase; + + let j: number; + j = this._terminal.rows - 1 - this._terminal.buffer.scrollBottom; + j = this._terminal.rows - 1 + this._terminal.buffer.ybase - j; + while (param--) { + // test: echo -e '\e[44m\e[1M\e[0m' + // blankLine(true) - xterm/linux behavior + this._terminal.buffer.lines.splice(row, 1); + this._terminal.buffer.lines.splice(j, 0, this._terminal.blankLine(true)); + } + + // this.maxRange(); + this._terminal.updateRange(this._terminal.buffer.y); + this._terminal.updateRange(this._terminal.buffer.scrollBottom); + } + + /** + * CSI Ps P + * Delete Ps Character(s) (default = 1) (DCH). + */ + public deleteChars(params: number[]): void { + let param: number = params[0]; + if (param < 1) { + param = 1; + } + + const row = this._terminal.buffer.y + this._terminal.buffer.ybase; + const ch: CharData = [this._terminal.eraseAttr(), ' ', 1, 32]; // xterm + + while (param--) { + this._terminal.buffer.lines.get(row).splice(this._terminal.buffer.x, 1); + this._terminal.buffer.lines.get(row).push(ch); + } + this._terminal.updateRange(this._terminal.buffer.y); + } + + /** + * CSI Ps S Scroll up Ps lines (default = 1) (SU). + */ + public scrollUp(params: number[]): void { + let param = params[0] || 1; + while (param--) { + this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollTop, 1); + this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollBottom, 0, this._terminal.blankLine()); + } + // this.maxRange(); + this._terminal.updateRange(this._terminal.buffer.scrollTop); + this._terminal.updateRange(this._terminal.buffer.scrollBottom); + } + + /** + * CSI Ps T Scroll down Ps lines (default = 1) (SD). + */ + public scrollDown(params: number[]): void { + let param = params[0] || 1; + while (param--) { + this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollBottom, 1); + this._terminal.buffer.lines.splice(this._terminal.buffer.ybase + this._terminal.buffer.scrollTop, 0, this._terminal.blankLine()); + } + // this.maxRange(); + this._terminal.updateRange(this._terminal.buffer.scrollTop); + this._terminal.updateRange(this._terminal.buffer.scrollBottom); + } + + /** + * CSI Ps X + * Erase Ps Character(s) (default = 1) (ECH). + */ + public eraseChars(params: number[]): void { + let param = params[0]; + if (param < 1) { + param = 1; + } + + const row = this._terminal.buffer.y + this._terminal.buffer.ybase; + let j = this._terminal.buffer.x; + const ch: CharData = [this._terminal.eraseAttr(), ' ', 1, 32]; // xterm + + while (param-- && j < this._terminal.cols) { + this._terminal.buffer.lines.get(row)[j++] = ch; + } + } + + /** + * CSI Ps Z Cursor Backward Tabulation Ps tab stops (default = 1) (CBT). + */ + public cursorBackwardTab(params: number[]): void { + let param = params[0] || 1; + while (param--) { + this._terminal.buffer.x = this._terminal.buffer.prevStop(); + } + } + + /** + * CSI Pm ` Character Position Absolute + * [column] (default = [row,1]) (HPA). + */ + public charPosAbsolute(params: number[]): void { + let param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.x = param - 1; + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x = this._terminal.cols - 1; + } + } + + /** + * CSI Pm a Character Position Relative + * [columns] (default = [row,col+1]) (HPR) + * reuse CSI Ps C ? + */ + public HPositionRelative(params: number[]): void { + let param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.x += param; + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x = this._terminal.cols - 1; + } + } + + /** + * CSI Ps b Repeat the preceding graphic character Ps times (REP). + */ + public repeatPrecedingCharacter(params: number[]): void { + let param = params[0] || 1; + const line = this._terminal.buffer.lines.get(this._terminal.buffer.ybase + this._terminal.buffer.y); + const ch = line[this._terminal.buffer.x - 1] || [this._terminal.defAttr, ' ', 1, 32]; + + while (param--) { + line[this._terminal.buffer.x++] = ch; + } + } + + /** + * CSI Ps c Send Device Attributes (Primary DA). + * Ps = 0 or omitted -> request attributes from terminal. The + * response depends on the decTerminalID resource setting. + * -> CSI ? 1 ; 2 c (``VT100 with Advanced Video Option'') + * -> CSI ? 1 ; 0 c (``VT101 with No Options'') + * -> CSI ? 6 c (``VT102'') + * -> CSI ? 6 0 ; 1 ; 2 ; 6 ; 8 ; 9 ; 1 5 ; c (``VT220'') + * The VT100-style response parameters do not mean anything by + * themselves. VT220 parameters do, telling the host what fea- + * tures the terminal supports: + * Ps = 1 -> 132-columns. + * Ps = 2 -> Printer. + * Ps = 6 -> Selective erase. + * Ps = 8 -> User-defined keys. + * Ps = 9 -> National replacement character sets. + * Ps = 1 5 -> Technical characters. + * Ps = 2 2 -> ANSI color, e.g., VT525. + * Ps = 2 9 -> ANSI text locator (i.e., DEC Locator mode). + * CSI > Ps c + * Send Device Attributes (Secondary DA). + * Ps = 0 or omitted -> request the terminal's identification + * code. The response depends on the decTerminalID resource set- + * ting. It should apply only to VT220 and up, but xterm extends + * this to VT100. + * -> CSI > Pp ; Pv ; Pc c + * where Pp denotes the terminal type + * Pp = 0 -> ``VT100''. + * Pp = 1 -> ``VT220''. + * and Pv is the firmware version (for xterm, this was originally + * the XFree86 patch number, starting with 95). In a DEC termi- + * nal, Pc indicates the ROM cartridge registration number and is + * always zero. + * More information: + * xterm/charproc.c - line 2012, for more information. + * vim responds with ^[[?0c or ^[[?1c after the terminal's response (?) + */ + public sendDeviceAttributes(params: number[]): void { + if (params[0] > 0) { + return; + } + + if (!this._terminal.prefix) { + if (this._terminal.is('xterm') || this._terminal.is('rxvt-unicode') || this._terminal.is('screen')) { + this._terminal.send(C0.ESC + '[?1;2c'); + } else if (this._terminal.is('linux')) { + this._terminal.send(C0.ESC + '[?6c'); + } + } else if (this._terminal.prefix === '>') { + // xterm and urxvt + // seem to spit this + // out around ~370 times (?). + if (this._terminal.is('xterm')) { + this._terminal.send(C0.ESC + '[>0;276;0c'); + } else if (this._terminal.is('rxvt-unicode')) { + this._terminal.send(C0.ESC + '[>85;95;0c'); + } else if (this._terminal.is('linux')) { + // not supported by linux console. + // linux console echoes parameters. + this._terminal.send(params[0] + 'c'); + } else if (this._terminal.is('screen')) { + this._terminal.send(C0.ESC + '[>83;40003;0c'); + } + } + } + + /** + * CSI Pm d Vertical Position Absolute (VPA) + * [row] (default = [1,column]) + */ + public linePosAbsolute(params: number[]): void { + let param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y = param - 1; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + } + + /** + * CSI Pm e Vertical Position Relative (VPR) + * [rows] (default = [row+1,column]) + * reuse CSI Ps B ? + */ + public VPositionRelative(params: number[]): void { + let param = params[0]; + if (param < 1) { + param = 1; + } + this._terminal.buffer.y += param; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + // If the end of the line is hit, prevent this action from wrapping around to the next line. + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x--; + } + } + + /** + * CSI Ps ; Ps f + * Horizontal and Vertical Position [row;column] (default = + * [1,1]) (HVP). + */ + public HVPosition(params: number[]): void { + if (params[0] < 1) params[0] = 1; + if (params[1] < 1) params[1] = 1; + + this._terminal.buffer.y = params[0] - 1; + if (this._terminal.buffer.y >= this._terminal.rows) { + this._terminal.buffer.y = this._terminal.rows - 1; + } + + this._terminal.buffer.x = params[1] - 1; + if (this._terminal.buffer.x >= this._terminal.cols) { + this._terminal.buffer.x = this._terminal.cols - 1; + } + } + + /** + * CSI Ps g Tab Clear (TBC). + * Ps = 0 -> Clear Current Column (default). + * Ps = 3 -> Clear All. + * Potentially: + * Ps = 2 -> Clear Stops on Line. + * http://vt100.net/annarbor/aaa-ug/section6.html + */ + public tabClear(params: number[]): void { + let param = params[0]; + if (param <= 0) { + delete this._terminal.buffer.tabs[this._terminal.buffer.x]; + } else if (param === 3) { + this._terminal.buffer.tabs = {}; + } + } + + /** + * CSI Pm h Set Mode (SM). + * Ps = 2 -> Keyboard Action Mode (AM). + * Ps = 4 -> Insert Mode (IRM). + * Ps = 1 2 -> Send/receive (SRM). + * Ps = 2 0 -> Automatic Newline (LNM). + * CSI ? Pm h + * DEC Private Mode Set (DECSET). + * Ps = 1 -> Application Cursor Keys (DECCKM). + * Ps = 2 -> Designate USASCII for character sets G0-G3 + * (DECANM), and set VT100 mode. + * Ps = 3 -> 132 Column Mode (DECCOLM). + * Ps = 4 -> Smooth (Slow) Scroll (DECSCLM). + * Ps = 5 -> Reverse Video (DECSCNM). + * Ps = 6 -> Origin Mode (DECOM). + * Ps = 7 -> Wraparound Mode (DECAWM). + * Ps = 8 -> Auto-repeat Keys (DECARM). + * Ps = 9 -> Send Mouse X & Y on button press. See the sec- + * tion Mouse Tracking. + * Ps = 1 0 -> Show toolbar (rxvt). + * Ps = 1 2 -> Start Blinking Cursor (att610). + * Ps = 1 8 -> Print form feed (DECPFF). + * Ps = 1 9 -> Set print extent to full screen (DECPEX). + * Ps = 2 5 -> Show Cursor (DECTCEM). + * Ps = 3 0 -> Show scrollbar (rxvt). + * Ps = 3 5 -> Enable font-shifting functions (rxvt). + * Ps = 3 8 -> Enter Tektronix Mode (DECTEK). + * Ps = 4 0 -> Allow 80 -> 132 Mode. + * Ps = 4 1 -> more(1) fix (see curses resource). + * Ps = 4 2 -> Enable Nation Replacement Character sets (DECN- + * RCM). + * Ps = 4 4 -> Turn On Margin Bell. + * Ps = 4 5 -> Reverse-wraparound Mode. + * Ps = 4 6 -> Start Logging. This is normally disabled by a + * compile-time option. + * Ps = 4 7 -> Use Alternate Screen Buffer. (This may be dis- + * abled by the titeInhibit resource). + * Ps = 6 6 -> Application keypad (DECNKM). + * Ps = 6 7 -> Backarrow key sends backspace (DECBKM). + * Ps = 1 0 0 0 -> Send Mouse X & Y on button press and + * release. See the section Mouse Tracking. + * Ps = 1 0 0 1 -> Use Hilite Mouse Tracking. + * Ps = 1 0 0 2 -> Use Cell Motion Mouse Tracking. + * Ps = 1 0 0 3 -> Use All Motion Mouse Tracking. + * Ps = 1 0 0 4 -> Send FocusIn/FocusOut events. + * Ps = 1 0 0 5 -> Enable Extended Mouse Mode. + * Ps = 1 0 1 0 -> Scroll to bottom on tty output (rxvt). + * Ps = 1 0 1 1 -> Scroll to bottom on key press (rxvt). + * Ps = 1 0 3 4 -> Interpret "meta" key, sets eighth bit. + * (enables the eightBitInput resource). + * Ps = 1 0 3 5 -> Enable special modifiers for Alt and Num- + * Lock keys. (This enables the numLock resource). + * Ps = 1 0 3 6 -> Send ESC when Meta modifies a key. (This + * enables the metaSendsEscape resource). + * Ps = 1 0 3 7 -> Send DEL from the editing-keypad Delete + * key. + * Ps = 1 0 3 9 -> Send ESC when Alt modifies a key. (This + * enables the altSendsEscape resource). + * Ps = 1 0 4 0 -> Keep selection even if not highlighted. + * (This enables the keepSelection resource). + * Ps = 1 0 4 1 -> Use the CLIPBOARD selection. (This enables + * the selectToClipboard resource). + * Ps = 1 0 4 2 -> Enable Urgency window manager hint when + * Control-G is received. (This enables the bellIsUrgent + * resource). + * Ps = 1 0 4 3 -> Enable raising of the window when Control-G + * is received. (enables the popOnBell resource). + * Ps = 1 0 4 7 -> Use Alternate Screen Buffer. (This may be + * disabled by the titeInhibit resource). + * Ps = 1 0 4 8 -> Save cursor as in DECSC. (This may be dis- + * abled by the titeInhibit resource). + * Ps = 1 0 4 9 -> Save cursor as in DECSC and use Alternate + * Screen Buffer, clearing it first. (This may be disabled by + * the titeInhibit resource). This combines the effects of the 1 + * 0 4 7 and 1 0 4 8 modes. Use this with terminfo-based + * applications rather than the 4 7 mode. + * Ps = 1 0 5 0 -> Set terminfo/termcap function-key mode. + * Ps = 1 0 5 1 -> Set Sun function-key mode. + * Ps = 1 0 5 2 -> Set HP function-key mode. + * Ps = 1 0 5 3 -> Set SCO function-key mode. + * Ps = 1 0 6 0 -> Set legacy keyboard emulation (X11R6). + * Ps = 1 0 6 1 -> Set VT220 keyboard emulation. + * Ps = 2 0 0 4 -> Set bracketed paste mode. + * Modes: + * http: *vt100.net/docs/vt220-rm/chapter4.html + */ + public setMode(params: number[]): void { + if (params.length > 1) { + for (let i = 0; i < params.length; i++) { + this.setMode([params[i]]); + } + + return; + } + + if (!this._terminal.prefix) { + switch (params[0]) { + case 4: + this._terminal.insertMode = true; + break; + case 20: + // this._t.convertEol = true; + break; + } + } else if (this._terminal.prefix === '?') { + switch (params[0]) { + case 1: + this._terminal.applicationCursor = true; + break; + case 2: + this._terminal.setgCharset(0, DEFAULT_CHARSET); + this._terminal.setgCharset(1, DEFAULT_CHARSET); + this._terminal.setgCharset(2, DEFAULT_CHARSET); + this._terminal.setgCharset(3, DEFAULT_CHARSET); + // set VT100 mode here + break; + case 3: // 132 col mode + this._terminal.savedCols = this._terminal.cols; + this._terminal.resize(132, this._terminal.rows); + break; + case 6: + this._terminal.originMode = true; + break; + case 7: + this._terminal.wraparoundMode = true; + break; + case 12: + // this.cursorBlink = true; + break; + case 66: + this._terminal.log('Serial port requested application keypad.'); + this._terminal.applicationKeypad = true; + this._terminal.viewport.syncScrollArea(); + break; + case 9: // X10 Mouse + // no release, no motion, no wheel, no modifiers. + case 1000: // vt200 mouse + // no motion. + // no modifiers, except control on the wheel. + case 1002: // button event mouse + case 1003: // any event mouse + // any event - sends motion events, + // even if there is no button held down. + + // TODO: Why are params[0] compares nested within a switch for params[0]? + + this._terminal.x10Mouse = params[0] === 9; + this._terminal.vt200Mouse = params[0] === 1000; + this._terminal.normalMouse = params[0] > 1000; + this._terminal.mouseEvents = true; + this._terminal.element.classList.add('enable-mouse-events'); + this._terminal.selectionManager.disable(); + this._terminal.log('Binding to mouse events.'); + break; + case 1004: // send focusin/focusout events + // focusin: ^[[I + // focusout: ^[[O + this._terminal.sendFocus = true; + break; + case 1005: // utf8 ext mode mouse + this._terminal.utfMouse = true; + // for wide terminals + // simply encodes large values as utf8 characters + break; + case 1006: // sgr ext mode mouse + this._terminal.sgrMouse = true; + // for wide terminals + // does not add 32 to fields + // press: ^[[ Keyboard Action Mode (AM). + * Ps = 4 -> Replace Mode (IRM). + * Ps = 1 2 -> Send/receive (SRM). + * Ps = 2 0 -> Normal Linefeed (LNM). + * CSI ? Pm l + * DEC Private Mode Reset (DECRST). + * Ps = 1 -> Normal Cursor Keys (DECCKM). + * Ps = 2 -> Designate VT52 mode (DECANM). + * Ps = 3 -> 80 Column Mode (DECCOLM). + * Ps = 4 -> Jump (Fast) Scroll (DECSCLM). + * Ps = 5 -> Normal Video (DECSCNM). + * Ps = 6 -> Normal Cursor Mode (DECOM). + * Ps = 7 -> No Wraparound Mode (DECAWM). + * Ps = 8 -> No Auto-repeat Keys (DECARM). + * Ps = 9 -> Don't send Mouse X & Y on button press. + * Ps = 1 0 -> Hide toolbar (rxvt). + * Ps = 1 2 -> Stop Blinking Cursor (att610). + * Ps = 1 8 -> Don't print form feed (DECPFF). + * Ps = 1 9 -> Limit print to scrolling region (DECPEX). + * Ps = 2 5 -> Hide Cursor (DECTCEM). + * Ps = 3 0 -> Don't show scrollbar (rxvt). + * Ps = 3 5 -> Disable font-shifting functions (rxvt). + * Ps = 4 0 -> Disallow 80 -> 132 Mode. + * Ps = 4 1 -> No more(1) fix (see curses resource). + * Ps = 4 2 -> Disable Nation Replacement Character sets (DEC- + * NRCM). + * Ps = 4 4 -> Turn Off Margin Bell. + * Ps = 4 5 -> No Reverse-wraparound Mode. + * Ps = 4 6 -> Stop Logging. (This is normally disabled by a + * compile-time option). + * Ps = 4 7 -> Use Normal Screen Buffer. + * Ps = 6 6 -> Numeric keypad (DECNKM). + * Ps = 6 7 -> Backarrow key sends delete (DECBKM). + * Ps = 1 0 0 0 -> Don't send Mouse X & Y on button press and + * release. See the section Mouse Tracking. + * Ps = 1 0 0 1 -> Don't use Hilite Mouse Tracking. + * Ps = 1 0 0 2 -> Don't use Cell Motion Mouse Tracking. + * Ps = 1 0 0 3 -> Don't use All Motion Mouse Tracking. + * Ps = 1 0 0 4 -> Don't send FocusIn/FocusOut events. + * Ps = 1 0 0 5 -> Disable Extended Mouse Mode. + * Ps = 1 0 1 0 -> Don't scroll to bottom on tty output + * (rxvt). + * Ps = 1 0 1 1 -> Don't scroll to bottom on key press (rxvt). + * Ps = 1 0 3 4 -> Don't interpret "meta" key. (This disables + * the eightBitInput resource). + * Ps = 1 0 3 5 -> Disable special modifiers for Alt and Num- + * Lock keys. (This disables the numLock resource). + * Ps = 1 0 3 6 -> Don't send ESC when Meta modifies a key. + * (This disables the metaSendsEscape resource). + * Ps = 1 0 3 7 -> Send VT220 Remove from the editing-keypad + * Delete key. + * Ps = 1 0 3 9 -> Don't send ESC when Alt modifies a key. + * (This disables the altSendsEscape resource). + * Ps = 1 0 4 0 -> Do not keep selection when not highlighted. + * (This disables the keepSelection resource). + * Ps = 1 0 4 1 -> Use the PRIMARY selection. (This disables + * the selectToClipboard resource). + * Ps = 1 0 4 2 -> Disable Urgency window manager hint when + * Control-G is received. (This disables the bellIsUrgent + * resource). + * Ps = 1 0 4 3 -> Disable raising of the window when Control- + * G is received. (This disables the popOnBell resource). + * Ps = 1 0 4 7 -> Use Normal Screen Buffer, clearing screen + * first if in the Alternate Screen. (This may be disabled by + * the titeInhibit resource). + * Ps = 1 0 4 8 -> Restore cursor as in DECRC. (This may be + * disabled by the titeInhibit resource). + * Ps = 1 0 4 9 -> Use Normal Screen Buffer and restore cursor + * as in DECRC. (This may be disabled by the titeInhibit + * resource). This combines the effects of the 1 0 4 7 and 1 0 + * 4 8 modes. Use this with terminfo-based applications rather + * than the 4 7 mode. + * Ps = 1 0 5 0 -> Reset terminfo/termcap function-key mode. + * Ps = 1 0 5 1 -> Reset Sun function-key mode. + * Ps = 1 0 5 2 -> Reset HP function-key mode. + * Ps = 1 0 5 3 -> Reset SCO function-key mode. + * Ps = 1 0 6 0 -> Reset legacy keyboard emulation (X11R6). + * Ps = 1 0 6 1 -> Reset keyboard emulation to Sun/PC style. + * Ps = 2 0 0 4 -> Reset bracketed paste mode. + */ + public resetMode(params: number[]): void { + if (params.length > 1) { + for (let i = 0; i < params.length; i++) { + this.resetMode([params[i]]); + } + + return; + } + + if (!this._terminal.prefix) { + switch (params[0]) { + case 4: + this._terminal.insertMode = false; + break; + case 20: + // this._t.convertEol = false; + break; + } + } else if (this._terminal.prefix === '?') { + switch (params[0]) { + case 1: + this._terminal.applicationCursor = false; + break; + case 3: + if (this._terminal.cols === 132 && this._terminal.savedCols) { + this._terminal.resize(this._terminal.savedCols, this._terminal.rows); + } + delete this._terminal.savedCols; + break; + case 6: + this._terminal.originMode = false; + break; + case 7: + this._terminal.wraparoundMode = false; + break; + case 12: + // this.cursorBlink = false; + break; + case 66: + this._terminal.log('Switching back to normal keypad.'); + this._terminal.applicationKeypad = false; + this._terminal.viewport.syncScrollArea(); + break; + case 9: // X10 Mouse + case 1000: // vt200 mouse + case 1002: // button event mouse + case 1003: // any event mouse + this._terminal.x10Mouse = false; + this._terminal.vt200Mouse = false; + this._terminal.normalMouse = false; + this._terminal.mouseEvents = false; + this._terminal.element.classList.remove('enable-mouse-events'); + this._terminal.selectionManager.enable(); + break; + case 1004: // send focusin/focusout events + this._terminal.sendFocus = false; + break; + case 1005: // utf8 ext mode mouse + this._terminal.utfMouse = false; + break; + case 1006: // sgr ext mode mouse + this._terminal.sgrMouse = false; + break; + case 1015: // urxvt ext mode mouse + this._terminal.urxvtMouse = false; + break; + case 25: // hide cursor + this._terminal.cursorHidden = true; + break; + case 1049: // alt screen buffer cursor + // FALL-THROUGH + case 47: // normal screen buffer + case 1047: // normal screen buffer - clearing it first + // Ensure the selection manager has the correct buffer + this._terminal.buffers.activateNormalBuffer(); + // TODO: Not sure if we need to save/restore after switching the buffer + // if (params[0] === 1049) { + // this.restoreCursor(params); + // } + this._terminal.selectionManager.setBuffer(this._terminal.buffer); + this._terminal.refresh(0, this._terminal.rows - 1); + this._terminal.viewport.syncScrollArea(); + this._terminal.showCursor(); + break; + case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste) + this._terminal.bracketedPasteMode = false; + break; + } + } + } + + /** + * CSI Pm m Character Attributes (SGR). + * Ps = 0 -> Normal (default). + * Ps = 1 -> Bold. + * Ps = 2 -> Faint, decreased intensity (ISO 6429). + * Ps = 4 -> Underlined. + * Ps = 5 -> Blink (appears as Bold). + * Ps = 7 -> Inverse. + * Ps = 8 -> Invisible, i.e., hidden (VT300). + * Ps = 2 2 -> Normal (neither bold nor faint). + * Ps = 2 4 -> Not underlined. + * Ps = 2 5 -> Steady (not blinking). + * Ps = 2 7 -> Positive (not inverse). + * Ps = 2 8 -> Visible, i.e., not hidden (VT300). + * Ps = 3 0 -> Set foreground color to Black. + * Ps = 3 1 -> Set foreground color to Red. + * Ps = 3 2 -> Set foreground color to Green. + * Ps = 3 3 -> Set foreground color to Yellow. + * Ps = 3 4 -> Set foreground color to Blue. + * Ps = 3 5 -> Set foreground color to Magenta. + * Ps = 3 6 -> Set foreground color to Cyan. + * Ps = 3 7 -> Set foreground color to White. + * Ps = 3 9 -> Set foreground color to default (original). + * Ps = 4 0 -> Set background color to Black. + * Ps = 4 1 -> Set background color to Red. + * Ps = 4 2 -> Set background color to Green. + * Ps = 4 3 -> Set background color to Yellow. + * Ps = 4 4 -> Set background color to Blue. + * Ps = 4 5 -> Set background color to Magenta. + * Ps = 4 6 -> Set background color to Cyan. + * Ps = 4 7 -> Set background color to White. + * Ps = 4 9 -> Set background color to default (original). + * + * If 16-color support is compiled, the following apply. Assume + * that xterm's resources are set so that the ISO color codes are + * the first 8 of a set of 16. Then the aixterm colors are the + * bright versions of the ISO colors: + * Ps = 9 0 -> Set foreground color to Black. + * Ps = 9 1 -> Set foreground color to Red. + * Ps = 9 2 -> Set foreground color to Green. + * Ps = 9 3 -> Set foreground color to Yellow. + * Ps = 9 4 -> Set foreground color to Blue. + * Ps = 9 5 -> Set foreground color to Magenta. + * Ps = 9 6 -> Set foreground color to Cyan. + * Ps = 9 7 -> Set foreground color to White. + * Ps = 1 0 0 -> Set background color to Black. + * Ps = 1 0 1 -> Set background color to Red. + * Ps = 1 0 2 -> Set background color to Green. + * Ps = 1 0 3 -> Set background color to Yellow. + * Ps = 1 0 4 -> Set background color to Blue. + * Ps = 1 0 5 -> Set background color to Magenta. + * Ps = 1 0 6 -> Set background color to Cyan. + * Ps = 1 0 7 -> Set background color to White. + * + * If xterm is compiled with the 16-color support disabled, it + * supports the following, from rxvt: + * Ps = 1 0 0 -> Set foreground and background color to + * default. + * + * If 88- or 256-color support is compiled, the following apply. + * Ps = 3 8 ; 5 ; Ps -> Set foreground color to the second + * Ps. + * Ps = 4 8 ; 5 ; Ps -> Set background color to the second + * Ps. + */ + public charAttributes(params: number[]): void { + // Optimize a single SGR0. + if (params.length === 1 && params[0] === 0) { + this._terminal.curAttr = this._terminal.defAttr; + return; + } + + const l = params.length; + let flags = this._terminal.curAttr >> 18; + let fg = (this._terminal.curAttr >> 9) & 0x1ff; + let bg = this._terminal.curAttr & 0x1ff; + let p; + + for (let i = 0; i < l; i++) { + p = params[i]; + if (p >= 30 && p <= 37) { + // fg color 8 + fg = p - 30; + } else if (p >= 40 && p <= 47) { + // bg color 8 + bg = p - 40; + } else if (p >= 90 && p <= 97) { + // fg color 16 + p += 8; + fg = p - 90; + } else if (p >= 100 && p <= 107) { + // bg color 16 + p += 8; + bg = p - 100; + } else if (p === 0) { + // default + flags = this._terminal.defAttr >> 18; + fg = (this._terminal.defAttr >> 9) & 0x1ff; + bg = this._terminal.defAttr & 0x1ff; + // flags = 0; + // fg = 0x1ff; + // bg = 0x1ff; + } else if (p === 1) { + // bold text + flags |= FLAGS.BOLD; + } else if (p === 4) { + // underlined text + flags |= FLAGS.UNDERLINE; + } else if (p === 5) { + // blink + flags |= FLAGS.BLINK; + } else if (p === 7) { + // inverse and positive + // test with: echo -e '\e[31m\e[42mhello\e[7mworld\e[27mhi\e[m' + flags |= FLAGS.INVERSE; + } else if (p === 8) { + // invisible + flags |= FLAGS.INVISIBLE; + } else if (p === 2) { + // dimmed text + flags |= FLAGS.DIM; + } else if (p === 22) { + // not bold nor faint + flags &= ~FLAGS.BOLD; + flags &= ~FLAGS.DIM; + } else if (p === 24) { + // not underlined + flags &= ~FLAGS.UNDERLINE; + } else if (p === 25) { + // not blink + flags &= ~FLAGS.BLINK; + } else if (p === 27) { + // not inverse + flags &= ~FLAGS.INVERSE; + } else if (p === 28) { + // not invisible + flags &= ~FLAGS.INVISIBLE; + } else if (p === 39) { + // reset fg + fg = (this._terminal.defAttr >> 9) & 0x1ff; + } else if (p === 49) { + // reset bg + bg = this._terminal.defAttr & 0x1ff; + } else if (p === 38) { + // fg color 256 + if (params[i + 1] === 2) { + i += 2; + fg = this._terminal.matchColor( + params[i] & 0xff, + params[i + 1] & 0xff, + params[i + 2] & 0xff); + if (fg === -1) fg = 0x1ff; + i += 2; + } else if (params[i + 1] === 5) { + i += 2; + p = params[i] & 0xff; + fg = p; + } + } else if (p === 48) { + // bg color 256 + if (params[i + 1] === 2) { + i += 2; + bg = this._terminal.matchColor( + params[i] & 0xff, + params[i + 1] & 0xff, + params[i + 2] & 0xff); + if (bg === -1) bg = 0x1ff; + i += 2; + } else if (params[i + 1] === 5) { + i += 2; + p = params[i] & 0xff; + bg = p; + } + } else if (p === 100) { + // reset fg/bg + fg = (this._terminal.defAttr >> 9) & 0x1ff; + bg = this._terminal.defAttr & 0x1ff; + } else { + this._terminal.error('Unknown SGR attribute: %d.', p); + } + } + + this._terminal.curAttr = (flags << 18) | (fg << 9) | bg; + } + + /** + * CSI Ps n Device Status Report (DSR). + * Ps = 5 -> Status Report. Result (``OK'') is + * CSI 0 n + * Ps = 6 -> Report Cursor Position (CPR) [row;column]. + * Result is + * CSI r ; c R + * CSI ? Ps n + * Device Status Report (DSR, DEC-specific). + * Ps = 6 -> Report Cursor Position (CPR) [row;column] as CSI + * ? r ; c R (assumes page is zero). + * Ps = 1 5 -> Report Printer status as CSI ? 1 0 n (ready). + * or CSI ? 1 1 n (not ready). + * Ps = 2 5 -> Report UDK status as CSI ? 2 0 n (unlocked) + * or CSI ? 2 1 n (locked). + * Ps = 2 6 -> Report Keyboard status as + * CSI ? 2 7 ; 1 ; 0 ; 0 n (North American). + * The last two parameters apply to VT400 & up, and denote key- + * board ready and LK01 respectively. + * Ps = 5 3 -> Report Locator status as + * CSI ? 5 3 n Locator available, if compiled-in, or + * CSI ? 5 0 n No Locator, if not. + */ + public deviceStatus(params: number[]): void { + if (!this._terminal.prefix) { + switch (params[0]) { + case 5: + // status report + this._terminal.send(C0.ESC + '[0n'); + break; + case 6: + // cursor position + this._terminal.send(C0.ESC + '[' + + (this._terminal.buffer.y + 1) + + ';' + + (this._terminal.buffer.x + 1) + + 'R'); + break; + } + } else if (this._terminal.prefix === '?') { + // modern xterm doesnt seem to + // respond to any of these except ?6, 6, and 5 + switch (params[0]) { + case 6: + // cursor position + this._terminal.send(C0.ESC + '[?' + + (this._terminal.buffer.y + 1) + + ';' + + (this._terminal.buffer.x + 1) + + 'R'); + break; + case 15: + // no printer + // this.send(C0.ESC + '[?11n'); + break; + case 25: + // dont support user defined keys + // this.send(C0.ESC + '[?21n'); + break; + case 26: + // north american keyboard + // this.send(C0.ESC + '[?27;1;0;0n'); + break; + case 53: + // no dec locator/mouse + // this.send(C0.ESC + '[?50n'); + break; + } + } + } + + /** + * CSI ! p Soft terminal reset (DECSTR). + * http://vt100.net/docs/vt220-rm/table4-10.html + */ + public softReset(params: number[]): void { + this._terminal.cursorHidden = false; + this._terminal.insertMode = false; + this._terminal.originMode = false; + this._terminal.wraparoundMode = true; // defaults: xterm - true, vt100 - false + this._terminal.applicationKeypad = false; // ? + this._terminal.viewport.syncScrollArea(); + this._terminal.applicationCursor = false; + this._terminal.buffer.scrollTop = 0; + this._terminal.buffer.scrollBottom = this._terminal.rows - 1; + this._terminal.curAttr = this._terminal.defAttr; + this._terminal.buffer.x = this._terminal.buffer.y = 0; // ? + this._terminal.charset = null; + this._terminal.glevel = 0; // ?? + this._terminal.charsets = [null]; // ?? + } + + /** + * CSI Ps SP q Set cursor style (DECSCUSR, VT520). + * Ps = 0 -> blinking block. + * Ps = 1 -> blinking block (default). + * Ps = 2 -> steady block. + * Ps = 3 -> blinking underline. + * Ps = 4 -> steady underline. + * Ps = 5 -> blinking bar (xterm). + * Ps = 6 -> steady bar (xterm). + */ + public setCursorStyle(params?: number[]): void { + const param = params[0] < 1 ? 1 : params[0]; + switch (param) { + case 1: + case 2: + this._terminal.setOption('cursorStyle', 'block'); + break; + case 3: + case 4: + this._terminal.setOption('cursorStyle', 'underline'); + break; + case 5: + case 6: + this._terminal.setOption('cursorStyle', 'bar'); + break; + } + const isBlinking = param % 2 === 1; + this._terminal.setOption('cursorBlink', isBlinking); + } + + /** + * CSI Ps ; Ps r + * Set Scrolling Region [top;bottom] (default = full size of win- + * dow) (DECSTBM). + * CSI ? Pm r + */ + public setScrollRegion(params: number[]): void { + if (this._terminal.prefix) return; + this._terminal.buffer.scrollTop = (params[0] || 1) - 1; + this._terminal.buffer.scrollBottom = (params[1] && params[1] <= this._terminal.rows ? params[1] : this._terminal.rows) - 1; + this._terminal.buffer.x = 0; + this._terminal.buffer.y = 0; + } + + + /** + * CSI s + * Save cursor (ANSI.SYS). + */ + public saveCursor(params: number[]): void { + this._terminal.buffer.savedX = this._terminal.buffer.x; + this._terminal.buffer.savedY = this._terminal.buffer.y; + } + + + /** + * CSI u + * Restore cursor (ANSI.SYS). + */ + public restoreCursor(params: number[]): void { + this._terminal.buffer.x = this._terminal.buffer.savedX || 0; + this._terminal.buffer.y = this._terminal.buffer.savedY || 0; + } +} diff --git a/xterm.js/src/Interfaces.ts b/xterm.js/src/Interfaces.ts new file mode 100644 index 0000000..9a37a09 --- /dev/null +++ b/xterm.js/src/Interfaces.ts @@ -0,0 +1,355 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ILinkMatcherOptions } from './Interfaces'; +import { LinkMatcherHandler, LinkMatcherValidationCallback, Charset, LineData } from './Types'; +import { IColorSet, IRenderer } from './renderer/Interfaces'; +import { IMouseZoneManager } from './input/Interfaces'; + +export interface IBrowser { + isNode: boolean; + userAgent: string; + platform: string; + isFirefox: boolean; + isMSIE: boolean; + isMac: boolean; + isIpad: boolean; + isIphone: boolean; + isMSWindows: boolean; +} + +export interface IBufferAccessor { + buffer: IBuffer; +} + +export interface IElementAccessor { + element: HTMLElement; +} + +export interface ILinkifierAccessor { + linkifier: ILinkifier; +} + +export interface ITerminal extends ILinkifierAccessor, IBufferAccessor, IElementAccessor, IEventEmitter { + selectionManager: ISelectionManager; + charMeasure: ICharMeasure; + textarea: HTMLTextAreaElement; + renderer: IRenderer; + rows: number; + cols: number; + browser: IBrowser; + writeBuffer: string[]; + cursorHidden: boolean; + cursorState: number; + defAttr: number; + options: ITerminalOptions; + buffers: IBufferSet; + isFocused: boolean; + mouseHelper: IMouseHelper; + bracketedPasteMode: boolean; + + /** + * Emit the 'data' event and populate the given data. + * @param data The data to populate in the event. + */ + handler(data: string): void; + scrollLines(disp: number, suppressScrollEvent?: boolean): void; + cancel(ev: Event, force?: boolean): boolean | void; + log(text: string): void; + reset(): void; + showCursor(): void; + blankLine(cur?: boolean, isWrapped?: boolean, cols?: number): LineData; + refresh(start: number, end: number): void; +} + +/** + * This interface encapsulates everything needed from the Terminal by the + * InputHandler. This cleanly separates the large amount of methods needed by + * InputHandler cleanly from the ITerminal interface. + */ +export interface IInputHandlingTerminal extends IEventEmitter { + element: HTMLElement; + options: ITerminalOptions; + cols: number; + rows: number; + charset: Charset; + gcharset: number; + glevel: number; + charsets: Charset[]; + applicationKeypad: boolean; + applicationCursor: boolean; + originMode: boolean; + insertMode: boolean; + wraparoundMode: boolean; + bracketedPasteMode: boolean; + defAttr: number; + curAttr: number; + prefix: string; + savedCols: number; + x10Mouse: boolean; + vt200Mouse: boolean; + normalMouse: boolean; + mouseEvents: boolean; + sendFocus: boolean; + utfMouse: boolean; + sgrMouse: boolean; + urxvtMouse: boolean; + cursorHidden: boolean; + + buffers: IBufferSet; + buffer: IBuffer; + viewport: IViewport; + selectionManager: ISelectionManager; + + bell(): void; + focus(): void; + convertEol: boolean; + updateRange(y: number): void; + scroll(isWrapped?: boolean): void; + setgLevel(g: number): void; + eraseAttr(): number; + eraseRight(x: number, y: number): void; + eraseLine(y: number): void; + eraseLeft(x: number, y: number): void; + blankLine(cur?: boolean, isWrapped?: boolean): LineData; + is(term: string): boolean; + send(data: string): void; + setgCharset(g: number, charset: Charset): void; + resize(x: number, y: number): void; + log(text: string, data?: any): void; + reset(): void; + showCursor(): void; + refresh(start: number, end: number): void; + matchColor(r1: number, g1: number, b1: number): number; + error(text: string, data?: any): void; + setOption(key: string, value: any): void; +} + +export interface ITerminalOptions { + bellSound?: string; + bellStyle?: string; + cancelEvents?: boolean; + cols?: number; + convertEol?: boolean; + cursorBlink?: boolean; + cursorStyle?: string; + debug?: boolean; + disableStdin?: boolean; + enableBold?: boolean; + fontSize?: number; + fontFamily?: string; + handler?: (data: string) => void; + letterSpacing?: number; + lineHeight?: number; + rows?: number; + screenKeys?: boolean; + scrollback?: number; + tabStopWidth?: number; + termName?: string; + theme?: ITheme; + useFlowControl?: boolean; + allowTransparency?: boolean; +} + +export interface IBuffer { + lines: ICircularList; + ydisp: number; + ybase: number; + y: number; + x: number; + tabs: any; + scrollBottom: number; + scrollTop: number; + savedY: number; + savedX: number; + isCursorInViewport: boolean; + translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string; + nextStop(x?: number): number; + prevStop(x?: number): number; +} + +export interface IBufferSet { + alt: IBuffer; + normal: IBuffer; + active: IBuffer; + + activateNormalBuffer(): void; + activateAltBuffer(): void; +} + +export interface IMouseHelper { + getCoords(event: {pageX: number, pageY: number}, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number, isSelection?: boolean): [number, number]; + getRawByteCoords(event: MouseEvent, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number): { x: number, y: number }; +} + +export interface IViewport { + syncScrollArea(): void; + onWheel(ev: WheelEvent): void; + onTouchStart(ev: TouchEvent): void; + onTouchMove(ev: TouchEvent): void; + onThemeChanged(colors: IColorSet): void; +} + +export interface ISelectionManager { + selectionText: string; + selectionStart: [number, number]; + selectionEnd: [number, number]; + + disable(): void; + enable(): void; + setBuffer(buffer: IBuffer): void; + setSelection(row: number, col: number, length: number): void; +} + +export interface ICompositionHelper { + compositionstart(): void; + compositionupdate(ev: CompositionEvent): void; + compositionend(): void; + updateCompositionElements(dontRecurse?: boolean): void; + keydown(ev: KeyboardEvent): boolean; +} + +export interface ICharMeasure { + width: number; + height: number; + measure(options: ITerminalOptions): void; +} + +export interface ILinkifier extends IEventEmitter { + attachToDom(mouseZoneManager: IMouseZoneManager): void; + linkifyRows(start: number, end: number): void; + setHypertextLinkHandler(handler: LinkMatcherHandler): void; + setHypertextValidationCallback(callback: LinkMatcherValidationCallback): void; + registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options?: ILinkMatcherOptions): number; + deregisterLinkMatcher(matcherId: number): boolean; +} + +export interface ICircularList extends IEventEmitter { + length: number; + maxLength: number; + forEach: (callbackfn: (value: T, index: number) => void) => void; + + get(index: number): T; + set(index: number, value: T): void; + push(value: T): void; + pop(): T; + splice(start: number, deleteCount: number, ...items: T[]): void; + trimStart(count: number): void; + shiftElements(start: number, count: number, offset: number): void; +} + +export interface IEventEmitter { + on(type: string, listener: IListenerType): void; + off(type: string, listener: IListenerType): void; + emit(type: string, data?: any): void; +} + +export interface IListenerType { + (data?: any): void; + listener?: (data?: any) => void; +}; + +export interface ILinkMatcherOptions { + /** + * The index of the link from the regex.match(text) call. This defaults to 0 + * (for regular expressions without capture groups). + */ + matchIndex?: number; + /** + * A callback that validates an individual link, returning true if valid and + * false if invalid. + */ + validationCallback?: LinkMatcherValidationCallback; + /** + * A callback that fires when the mouse hovers over a link. + */ + tooltipCallback?: LinkMatcherHandler; + /** + * A callback that fires when the mouse leaves a link that was hovered. + */ + leaveCallback?: () => void; + /** + * The priority of the link matcher, this defines the order in which the link + * matcher is evaluated relative to others, from highest to lowest. The + * default value is 0. + */ + priority?: number; +} + +/** + * Handles actions generated by the parser. + */ +export interface IInputHandler { + addChar(char: string, code: number): void; + + /** C0 BEL */ bell(): void; + /** C0 LF */ lineFeed(): void; + /** C0 CR */ carriageReturn(): void; + /** C0 BS */ backspace(): void; + /** C0 HT */ tab(): void; + /** C0 SO */ shiftOut(): void; + /** C0 SI */ shiftIn(): void; + + /** CSI @ */ insertChars(params?: number[]): void; + /** CSI A */ cursorUp(params?: number[]): void; + /** CSI B */ cursorDown(params?: number[]): void; + /** CSI C */ cursorForward(params?: number[]): void; + /** CSI D */ cursorBackward(params?: number[]): void; + /** CSI E */ cursorNextLine(params?: number[]): void; + /** CSI F */ cursorPrecedingLine(params?: number[]): void; + /** CSI G */ cursorCharAbsolute(params?: number[]): void; + /** CSI H */ cursorPosition(params?: number[]): void; + /** CSI I */ cursorForwardTab(params?: number[]): void; + /** CSI J */ eraseInDisplay(params?: number[]): void; + /** CSI K */ eraseInLine(params?: number[]): void; + /** CSI L */ insertLines(params?: number[]): void; + /** CSI M */ deleteLines(params?: number[]): void; + /** CSI P */ deleteChars(params?: number[]): void; + /** CSI S */ scrollUp(params?: number[]): void; + /** CSI T */ scrollDown(params?: number[]): void; + /** CSI X */ eraseChars(params?: number[]): void; + /** CSI Z */ cursorBackwardTab(params?: number[]): void; + /** CSI ` */ charPosAbsolute(params?: number[]): void; + /** CSI a */ HPositionRelative(params?: number[]): void; + /** CSI b */ repeatPrecedingCharacter(params?: number[]): void; + /** CSI c */ sendDeviceAttributes(params?: number[]): void; + /** CSI d */ linePosAbsolute(params?: number[]): void; + /** CSI e */ VPositionRelative(params?: number[]): void; + /** CSI f */ HVPosition(params?: number[]): void; + /** CSI g */ tabClear(params?: number[]): void; + /** CSI h */ setMode(params?: number[]): void; + /** CSI l */ resetMode(params?: number[]): void; + /** CSI m */ charAttributes(params?: number[]): void; + /** CSI n */ deviceStatus(params?: number[]): void; + /** CSI p */ softReset(params?: number[]): void; + /** CSI q */ setCursorStyle(params?: number[]): void; + /** CSI r */ setScrollRegion(params?: number[]): void; + /** CSI s */ saveCursor(params?: number[]): void; + /** CSI u */ restoreCursor(params?: number[]): void; +} + +export interface ITheme { + foreground?: string; + background?: string; + cursor?: string; + cursorAccent?: string; + selection?: string; + black?: string; + red?: string; + green?: string; + yellow?: string; + blue?: string; + magenta?: string; + cyan?: string; + white?: string; + brightBlack?: string; + brightRed?: string; + brightGreen?: string; + brightYellow?: string; + brightBlue?: string; + brightMagenta?: string; + brightCyan?: string; + brightWhite?: string; +} diff --git a/xterm.js/src/Linkifier.test.ts b/xterm.js/src/Linkifier.test.ts new file mode 100644 index 0000000..0878aaf --- /dev/null +++ b/xterm.js/src/Linkifier.test.ts @@ -0,0 +1,220 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert } from 'chai'; +import { ITerminal, ILinkifier, IBuffer, IBufferAccessor, IElementAccessor } from './Interfaces'; +import { Linkifier } from './Linkifier'; +import { LinkMatcher, LineData } from './Types'; +import { IMouseZoneManager, IMouseZone } from './input/Interfaces'; +import { MockBuffer } from './utils/TestUtils.test'; +import { CircularList } from './utils/CircularList'; + +class TestLinkifier extends Linkifier { + constructor(_terminal: IBufferAccessor & IElementAccessor) { + super(_terminal); + Linkifier.TIME_BEFORE_LINKIFY = 0; + } + + public get linkMatchers(): LinkMatcher[] { return this._linkMatchers; } + public linkifyRows(): void { super.linkifyRows(0, this._terminal.buffer.lines.length - 1); } +} + +class TestMouseZoneManager implements IMouseZoneManager { + public clears: number = 0; + public zones: IMouseZone[] = []; + add(zone: IMouseZone): void { + this.zones.push(zone); + } + clearAll(): void { + this.clears++; + } +} + +describe('Linkifier', () => { + let terminal: IBufferAccessor & IElementAccessor; + let linkifier: TestLinkifier; + let mouseZoneManager: TestMouseZoneManager; + + beforeEach(() => { + terminal = { + buffer: new MockBuffer(), + element: {} + }; + terminal.buffer.lines = new CircularList(20); + terminal.buffer.ydisp = 0; + linkifier = new TestLinkifier(terminal); + mouseZoneManager = new TestMouseZoneManager(); + }); + + function stringToRow(text: string): LineData { + let result: LineData = []; + for (let i = 0; i < text.length; i++) { + result.push([0, text.charAt(i), 1, text.charCodeAt(i)]); + } + return result; + } + + function addRow(text: string): void { + terminal.buffer.lines.push(stringToRow(text)); + } + + function assertLinkifiesEntireRow(uri: string, done: MochaDone): void { + addRow(uri); + linkifier.linkifyRows(); + setTimeout(() => { + assert.equal(mouseZoneManager.zones[0].x1, 1); + assert.equal(mouseZoneManager.zones[0].x2, uri.length + 1); + assert.equal(mouseZoneManager.zones[0].y, terminal.buffer.lines.length); + done(); + }, 0); + } + + function assertLinkifiesRow(rowText: string, linkMatcherRegex: RegExp, links: {x: number, length: number}[], done: MochaDone): void { + addRow(rowText); + linkifier.registerLinkMatcher(linkMatcherRegex, () => {}); + linkifier.linkifyRows(); + // Allow linkify to happen + setTimeout(() => { + assert.equal(mouseZoneManager.zones.length, links.length); + links.forEach((l, i) => { + assert.equal(mouseZoneManager.zones[i].x1, l.x + 1); + assert.equal(mouseZoneManager.zones[i].x2, l.x + l.length + 1); + assert.equal(mouseZoneManager.zones[i].y, terminal.buffer.lines.length); + }); + done(); + }, 0); + } + + describe('before attachToDom', () => { + it('should allow link matcher registration', done => { + assert.doesNotThrow(() => { + const linkMatcherId = linkifier.registerLinkMatcher(/foo/, () => {}); + assert.isTrue(linkifier.deregisterLinkMatcher(linkMatcherId)); + done(); + }); + }); + }); + + describe('after attachToDom', () => { + beforeEach(() => { + linkifier.attachToDom(mouseZoneManager); + }); + + describe('http links', () => { + it('should allow ~ character in URI path', (done) => { + assertLinkifiesEntireRow('http://foo.com/a~b#c~d?e~f', done); + }); + }); + + describe('link matcher', () => { + it('should match a single link', done => { + assertLinkifiesRow('foo', /foo/, [{x: 0, length: 3}], done); + }); + it('should match a single link at the start of a text node', done => { + assertLinkifiesRow('foo bar', /foo/, [{x: 0, length: 3}], done); + }); + it('should match a single link in the middle of a text node', done => { + assertLinkifiesRow('foo bar baz', /bar/, [{x: 4, length: 3}], done); + }); + it('should match a single link at the end of a text node', done => { + assertLinkifiesRow('foo bar', /bar/, [{x: 4, length: 3}], done); + }); + it('should match a link after a link at the start of a text node', done => { + assertLinkifiesRow('foo bar', /foo|bar/, [{x: 0, length: 3}, {x: 4, length: 3}], done); + }); + it('should match a link after a link in the middle of a text node', done => { + assertLinkifiesRow('foo bar baz', /bar|baz/, [{x: 4, length: 3}, {x: 8, length: 3}], done); + }); + it('should match a link immediately after a link at the end of a text node', done => { + assertLinkifiesRow('foo barbaz', /bar|baz/, [{x: 4, length: 3}, {x: 7, length: 3}], done); + }); + it('should not duplicate text after a unicode character (wrapped in a span)', done => { + // This is a regression test for an issue that came about when using + // an oh-my-zsh theme that added the large blue diamond unicode + // character (U+1F537) which caused the path to be duplicated. See #642. + assertLinkifiesRow('echo \'🔷foo\'', /foo/, [{x: 8, length: 3}], done); + }); + }); + + describe('validationCallback', () => { + it('should enable link if true', done => { + addRow('test'); + linkifier.registerLinkMatcher(/test/, () => done(), { + validationCallback: (url, cb) => { + assert.equal(mouseZoneManager.zones.length, 0); + cb(true); + assert.equal(mouseZoneManager.zones.length, 1); + assert.equal(mouseZoneManager.zones[0].x1, 1); + assert.equal(mouseZoneManager.zones[0].x2, 5); + assert.equal(mouseZoneManager.zones[0].y, 1); + // Fires done() + mouseZoneManager.zones[0].clickCallback({}); + } + }); + linkifier.linkifyRows(); + }); + + it('should validate the uri, not the row', done => { + addRow('abc test abc'); + linkifier.registerLinkMatcher(/test/, () => done(), { + validationCallback: (uri, cb) => { + assert.equal(uri, 'test'); + done(); + } + }); + linkifier.linkifyRows(); + }); + + it('should disable link if false', done => { + addRow('test'); + linkifier.registerLinkMatcher(/test/, () => assert.fail(), { + validationCallback: (url, cb) => { + assert.equal(mouseZoneManager.zones.length, 0); + cb(false); + assert.equal(mouseZoneManager.zones.length, 0); + } + }); + linkifier.linkifyRows(); + // Allow time for the validation callback to be performed + setTimeout(() => done(), 10); + }); + + it('should trigger for multiple link matches on one row', done => { + addRow('test test'); + let count = 0; + linkifier.registerLinkMatcher(/test/, () => assert.fail(), { + validationCallback: (url, cb) => { + count += 1; + if (count === 2) { + done(); + } + cb(false); + } + }); + linkifier.linkifyRows(); + }); + }); + + describe('priority', () => { + it('should order the list from highest priority to lowest #1', () => { + const aId = linkifier.registerLinkMatcher(/a/, () => {}, { priority: 1 }); + const bId = linkifier.registerLinkMatcher(/b/, () => {}, { priority: -1 }); + assert.deepEqual(linkifier.linkMatchers.map(lm => lm.id), [aId, 0, bId]); + }); + + it('should order the list from highest priority to lowest #2', () => { + const aId = linkifier.registerLinkMatcher(/a/, () => {}, { priority: -1 }); + const bId = linkifier.registerLinkMatcher(/b/, () => {}, { priority: 1 }); + assert.deepEqual(linkifier.linkMatchers.map(lm => lm.id), [bId, 0, aId]); + }); + + it('should order items of equal priority in the order they are added', () => { + const aId = linkifier.registerLinkMatcher(/a/, () => {}, { priority: 0 }); + const bId = linkifier.registerLinkMatcher(/b/, () => {}, { priority: 0 }); + assert.deepEqual(linkifier.linkMatchers.map(lm => lm.id), [0, aId, bId]); + }); + }); + }); +}); diff --git a/xterm.js/src/Linkifier.ts b/xterm.js/src/Linkifier.ts new file mode 100644 index 0000000..e6a63b5 --- /dev/null +++ b/xterm.js/src/Linkifier.ts @@ -0,0 +1,297 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ILinkMatcherOptions, ITerminal, IBufferAccessor, ILinkifier, IElementAccessor } from './Interfaces'; +import { LinkMatcher, LinkMatcherHandler, LinkMatcherValidationCallback, LineData, LinkHoverEvent, LinkHoverEventTypes } from './Types'; +import { IMouseZoneManager } from './input/Interfaces'; +import { MouseZone } from './input/MouseZoneManager'; +import { EventEmitter } from './EventEmitter'; + +const protocolClause = '(https?:\\/\\/)'; +const domainCharacterSet = '[\\da-z\\.-]+'; +const negatedDomainCharacterSet = '[^\\da-z\\.-]+'; +const domainBodyClause = '(' + domainCharacterSet + ')'; +const tldClause = '([a-z\\.]{2,6})'; +const ipClause = '((\\d{1,3}\\.){3}\\d{1,3})'; +const localHostClause = '(localhost)'; +const portClause = '(:\\d{1,5})'; +const hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?'; +const pathClause = '(\\/[\\/\\w\\.\\-%~]*)*'; +const queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*'; +const queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?'; +const hashFragmentClause = '(#' + queryStringHashFragmentCharacterSet + ')?'; +const negatedPathCharacterSet = '[^\\/\\w\\.\\-%]+'; +const bodyClause = hostClause + pathClause + queryStringClause + hashFragmentClause; +const start = '(?:^|' + negatedDomainCharacterSet + ')('; +const end = ')($|' + negatedPathCharacterSet + ')'; +const strictUrlRegex = new RegExp(start + protocolClause + bodyClause + end); + +/** + * The ID of the built in http(s) link matcher. + */ +const HYPERTEXT_LINK_MATCHER_ID = 0; + +/** + * The Linkifier applies links to rows shortly after they have been refreshed. + */ +export class Linkifier extends EventEmitter implements ILinkifier { + /** + * The time to wait after a row is changed before it is linkified. This prevents + * the costly operation of searching every row multiple times, potentially a + * huge amount of times. + */ + protected static TIME_BEFORE_LINKIFY = 200; + + protected _linkMatchers: LinkMatcher[] = []; + + private _mouseZoneManager: IMouseZoneManager; + private _rowsTimeoutId: number; + private _nextLinkMatcherId = HYPERTEXT_LINK_MATCHER_ID; + private _rowsToLinkify: {start: number, end: number}; + + constructor( + protected _terminal: IBufferAccessor & IElementAccessor + ) { + super(); + this._rowsToLinkify = { + start: null, + end: null + }; + this.registerLinkMatcher(strictUrlRegex, null, { matchIndex: 1 }); + } + + /** + * Attaches the linkifier to the DOM, enabling linkification. + * @param mouseZoneManager The mouse zone manager to register link zones with. + */ + public attachToDom(mouseZoneManager: IMouseZoneManager): void { + this._mouseZoneManager = mouseZoneManager; + } + + /** + * Queue linkification on a set of rows. + * @param start The row to linkify from (inclusive). + * @param end The row to linkify to (inclusive). + */ + public linkifyRows(start: number, end: number): void { + // Don't attempt linkify if not yet attached to DOM + if (!this._mouseZoneManager) { + return; + } + + // Increase range to linkify + if (!this._rowsToLinkify.start) { + this._rowsToLinkify.start = start; + this._rowsToLinkify.end = end; + } else { + this._rowsToLinkify.start = this._rowsToLinkify.start < start ? this._rowsToLinkify.start : start; + this._rowsToLinkify.end = this._rowsToLinkify.end > end ? this._rowsToLinkify.end : end; + } + + // Clear out any existing links on this row range + this._mouseZoneManager.clearAll(start, end); + + // Restart timer + if (this._rowsTimeoutId) { + clearTimeout(this._rowsTimeoutId); + } + this._rowsTimeoutId = setTimeout(() => this._linkifyRows(), Linkifier.TIME_BEFORE_LINKIFY); + } + + /** + * Linkifies the rows requested. + */ + private _linkifyRows(): void { + this._rowsTimeoutId = null; + for (let i = this._rowsToLinkify.start; i <= this._rowsToLinkify.end; i++) { + this._linkifyRow(i); + } + this._rowsToLinkify.start = null; + this._rowsToLinkify.end = null; + } + + /** + * Attaches a handler for hypertext links, overriding default behavior for + * tandard http(s) links. + * @param handler The handler to use, this can be cleared with null. + */ + public setHypertextLinkHandler(handler: LinkMatcherHandler): void { + this._linkMatchers[HYPERTEXT_LINK_MATCHER_ID].handler = handler; + } + + /** + * Attaches a validation callback for hypertext links. + * @param callback The callback to use, this can be cleared with null. + */ + public setHypertextValidationCallback(callback: LinkMatcherValidationCallback): void { + this._linkMatchers[HYPERTEXT_LINK_MATCHER_ID].validationCallback = callback; + } + + /** + * Registers a link matcher, allowing custom link patterns to be matched and + * handled. + * @param regex The regular expression to search for. Specifically, this + * searches the textContent of the rows. You will want to use \s to match a + * space ' ' character for example. + * @param handler The callback when the link is called. + * @param options Options for the link matcher. + * @return The ID of the new matcher, this can be used to deregister. + */ + public registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options: ILinkMatcherOptions = {}): number { + if (this._nextLinkMatcherId !== HYPERTEXT_LINK_MATCHER_ID && !handler) { + throw new Error('handler must be defined'); + } + const matcher: LinkMatcher = { + id: this._nextLinkMatcherId++, + regex, + handler, + matchIndex: options.matchIndex, + validationCallback: options.validationCallback, + hoverTooltipCallback: options.tooltipCallback, + hoverLeaveCallback: options.leaveCallback, + priority: options.priority || 0 + }; + this._addLinkMatcherToList(matcher); + return matcher.id; + } + + /** + * Inserts a link matcher to the list in the correct position based on the + * priority of each link matcher. New link matchers of equal priority are + * considered after older link matchers. + * @param matcher The link matcher to be added. + */ + private _addLinkMatcherToList(matcher: LinkMatcher): void { + if (this._linkMatchers.length === 0) { + this._linkMatchers.push(matcher); + return; + } + + for (let i = this._linkMatchers.length - 1; i >= 0; i--) { + if (matcher.priority <= this._linkMatchers[i].priority) { + this._linkMatchers.splice(i + 1, 0, matcher); + return; + } + } + + this._linkMatchers.splice(0, 0, matcher); + } + + /** + * Deregisters a link matcher if it has been registered. + * @param matcherId The link matcher's ID (returned after register) + * @return Whether a link matcher was found and deregistered. + */ + public deregisterLinkMatcher(matcherId: number): boolean { + // ID 0 is the hypertext link matcher which cannot be deregistered + for (let i = 1; i < this._linkMatchers.length; i++) { + if (this._linkMatchers[i].id === matcherId) { + this._linkMatchers.splice(i, 1); + return true; + } + } + return false; + } + + /** + * Linkifies a row. + * @param rowIndex The index of the row to linkify. + */ + private _linkifyRow(rowIndex: number): void { + const absoluteRowIndex = this._terminal.buffer.ydisp + rowIndex; + if (absoluteRowIndex >= this._terminal.buffer.lines.length) { + return; + } + const text = this._terminal.buffer.translateBufferLineToString(absoluteRowIndex, false); + for (let i = 0; i < this._linkMatchers.length; i++) { + this._doLinkifyRow(rowIndex, text, this._linkMatchers[i]); + } + } + + /** + * Linkifies a row given a specific handler. + * @param rowIndex The row index to linkify. + * @param text The text of the row (excludes text in the row that's already + * linkified). + * @param matcher The link matcher for this line. + * @param offset The how much of the row has already been linkified. + * @return The link element(s) that were added. + */ + private _doLinkifyRow(rowIndex: number, text: string, matcher: LinkMatcher, offset: number = 0): void { + // Iterate over nodes as we want to consider text nodes + let result = []; + const isHttpLinkMatcher = matcher.id === HYPERTEXT_LINK_MATCHER_ID; + + // Find the first match + let match = text.match(matcher.regex); + if (!match || match.length === 0) { + return; + } + let uri = match[typeof matcher.matchIndex !== 'number' ? 0 : matcher.matchIndex]; + + // Get index, match.index is for the outer match which includes negated chars + const index = text.indexOf(uri); + + // Ensure the link is valid before registering + if (matcher.validationCallback) { + matcher.validationCallback(uri, isValid => { + // Discard link if the line has already changed + if (this._rowsTimeoutId) { + return; + } + if (isValid) { + this._addLink(offset + index, rowIndex, uri, matcher); + } + }); + } else { + this._addLink(offset + index, rowIndex, uri, matcher); + } + + // Recursively check for links in the rest of the text + const remainingStartIndex = index + uri.length; + const remainingText = text.substr(remainingStartIndex); + if (remainingText.length > 0) { + this._doLinkifyRow(rowIndex, remainingText, matcher, offset + remainingStartIndex); + } + } + + /** + * Registers a link to the mouse zone manager. + * @param x The column the link starts. + * @param y The row the link is on. + * @param uri The URI of the link. + * @param matcher The link matcher for the link. + */ + private _addLink(x: number, y: number, uri: string, matcher: LinkMatcher): void { + this._mouseZoneManager.add(new MouseZone( + x + 1, + x + 1 + uri.length, + y + 1, + e => { + if (matcher.handler) { + return matcher.handler(e, uri); + } + window.open(uri, '_blank'); + }, + e => { + this.emit(LinkHoverEventTypes.HOVER, { x, y, length: uri.length}); + this._terminal.element.style.cursor = 'pointer'; + }, + e => { + this.emit(LinkHoverEventTypes.TOOLTIP, { x, y, length: uri.length}); + if (matcher.hoverTooltipCallback) { + matcher.hoverTooltipCallback(e, uri); + } + }, + () => { + this.emit(LinkHoverEventTypes.LEAVE, { x, y, length: uri.length}); + this._terminal.element.style.cursor = ''; + if (matcher.hoverLeaveCallback) { + matcher.hoverLeaveCallback(); + } + } + )); + } +} diff --git a/xterm.js/src/Parser.ts b/xterm.js/src/Parser.ts new file mode 100644 index 0000000..6f4b093 --- /dev/null +++ b/xterm.js/src/Parser.ts @@ -0,0 +1,673 @@ +/** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) + * @license MIT + */ + +import { C0 } from './EscapeSequences'; +import { IInputHandler } from './Interfaces'; +import { CHARSETS, DEFAULT_CHARSET } from './Charsets'; + +const normalStateHandler: {[key: string]: (parser: Parser, handler: IInputHandler) => void} = {}; +normalStateHandler[C0.BEL] = (parser, handler) => handler.bell(); +normalStateHandler[C0.LF] = (parser, handler) => handler.lineFeed(); +normalStateHandler[C0.VT] = normalStateHandler[C0.LF]; +normalStateHandler[C0.FF] = normalStateHandler[C0.LF]; +normalStateHandler[C0.CR] = (parser, handler) => handler.carriageReturn(); +normalStateHandler[C0.BS] = (parser, handler) => handler.backspace(); +normalStateHandler[C0.HT] = (parser, handler) => handler.tab(); +normalStateHandler[C0.SO] = (parser, handler) => handler.shiftOut(); +normalStateHandler[C0.SI] = (parser, handler) => handler.shiftIn(); +normalStateHandler[C0.ESC] = (parser, handler) => parser.setState(ParserState.ESCAPED); + +// TODO: Remove terminal when parser owns params and currentParam +const escapedStateHandler: {[key: string]: (parser: Parser, terminal: any) => void} = {}; +escapedStateHandler['['] = (parser, terminal) => { + // ESC [ Control Sequence Introducer (CSI is 0x9b) + terminal.params = []; + terminal.currentParam = 0; + parser.setState(ParserState.CSI_PARAM); +}; +escapedStateHandler[']'] = (parser, terminal) => { + // ESC ] Operating System Command (OSC is 0x9d) + terminal.params = []; + terminal.currentParam = 0; + parser.setState(ParserState.OSC); +}; +escapedStateHandler['P'] = (parser, terminal) => { + // ESC P Device Control String (DCS is 0x90) + terminal.params = []; + terminal.currentParam = 0; + parser.setState(ParserState.DCS); +}; +escapedStateHandler['_'] = (parser, terminal) => { + // ESC _ Application Program Command ( APC is 0x9f). + parser.setState(ParserState.IGNORE); +}; +escapedStateHandler['^'] = (parser, terminal) => { + // ESC ^ Privacy Message ( PM is 0x9e). + parser.setState(ParserState.IGNORE); +}; +escapedStateHandler['c'] = (parser, terminal) => { + // ESC c Full Reset (RIS). + terminal.reset(); +}; +escapedStateHandler['E'] = (parser, terminal) => { + // ESC E Next Line ( NEL is 0x85). + terminal.buffer.x = 0; + terminal.index(); + parser.setState(ParserState.NORMAL); +}; +escapedStateHandler['D'] = (parser, terminal) => { + // ESC D Index ( IND is 0x84). + terminal.index(); + parser.setState(ParserState.NORMAL); +}; +escapedStateHandler['M'] = (parser, terminal) => { + // ESC M Reverse Index ( RI is 0x8d). + terminal.reverseIndex(); + parser.setState(ParserState.NORMAL); +}; +escapedStateHandler['%'] = (parser, terminal) => { + // ESC % Select default/utf-8 character set. + // @ = default, G = utf-8 + terminal.setgLevel(0); + terminal.setgCharset(0, DEFAULT_CHARSET); // US (default) + parser.setState(ParserState.NORMAL); + parser.skipNextChar(); +}; +escapedStateHandler[C0.CAN] = (parser) => parser.setState(ParserState.NORMAL); + +const csiParamStateHandler: {[key: string]: (parser: Parser) => void} = {}; +csiParamStateHandler['?'] = (parser) => parser.setPrefix('?'); +csiParamStateHandler['>'] = (parser) => parser.setPrefix('>'); +csiParamStateHandler['!'] = (parser) => parser.setPrefix('!'); +csiParamStateHandler['0'] = (parser) => parser.setParam(parser.getParam() * 10); +csiParamStateHandler['1'] = (parser) => parser.setParam(parser.getParam() * 10 + 1); +csiParamStateHandler['2'] = (parser) => parser.setParam(parser.getParam() * 10 + 2); +csiParamStateHandler['3'] = (parser) => parser.setParam(parser.getParam() * 10 + 3); +csiParamStateHandler['4'] = (parser) => parser.setParam(parser.getParam() * 10 + 4); +csiParamStateHandler['5'] = (parser) => parser.setParam(parser.getParam() * 10 + 5); +csiParamStateHandler['6'] = (parser) => parser.setParam(parser.getParam() * 10 + 6); +csiParamStateHandler['7'] = (parser) => parser.setParam(parser.getParam() * 10 + 7); +csiParamStateHandler['8'] = (parser) => parser.setParam(parser.getParam() * 10 + 8); +csiParamStateHandler['9'] = (parser) => parser.setParam(parser.getParam() * 10 + 9); +csiParamStateHandler['$'] = (parser) => parser.setPostfix('$'); +csiParamStateHandler['"'] = (parser) => parser.setPostfix('"'); +csiParamStateHandler[' '] = (parser) => parser.setPostfix(' '); +csiParamStateHandler['\''] = (parser) => parser.setPostfix('\''); +csiParamStateHandler[';'] = (parser) => parser.finalizeParam(); +csiParamStateHandler[C0.CAN] = (parser) => parser.setState(ParserState.NORMAL); + +const csiStateHandler: {[key: string]: (handler: IInputHandler, params: number[], prefix: string, postfix: string, parser: Parser) => void} = {}; +csiStateHandler['@'] = (handler, params, prefix) => handler.insertChars(params); +csiStateHandler['A'] = (handler, params, prefix) => handler.cursorUp(params); +csiStateHandler['B'] = (handler, params, prefix) => handler.cursorDown(params); +csiStateHandler['C'] = (handler, params, prefix) => handler.cursorForward(params); +csiStateHandler['D'] = (handler, params, prefix) => handler.cursorBackward(params); +csiStateHandler['E'] = (handler, params, prefix) => handler.cursorNextLine(params); +csiStateHandler['F'] = (handler, params, prefix) => handler.cursorPrecedingLine(params); +csiStateHandler['G'] = (handler, params, prefix) => handler.cursorCharAbsolute(params); +csiStateHandler['H'] = (handler, params, prefix) => handler.cursorPosition(params); +csiStateHandler['I'] = (handler, params, prefix) => handler.cursorForwardTab(params); +csiStateHandler['J'] = (handler, params, prefix) => handler.eraseInDisplay(params); +csiStateHandler['K'] = (handler, params, prefix) => handler.eraseInLine(params); +csiStateHandler['L'] = (handler, params, prefix) => handler.insertLines(params); +csiStateHandler['M'] = (handler, params, prefix) => handler.deleteLines(params); +csiStateHandler['P'] = (handler, params, prefix) => handler.deleteChars(params); +csiStateHandler['S'] = (handler, params, prefix) => handler.scrollUp(params); +csiStateHandler['T'] = (handler, params, prefix) => { + if (params.length < 2 && !prefix) { + handler.scrollDown(params); + } +}; +csiStateHandler['X'] = (handler, params, prefix) => handler.eraseChars(params); +csiStateHandler['Z'] = (handler, params, prefix) => handler.cursorBackwardTab(params); +csiStateHandler['`'] = (handler, params, prefix) => handler.charPosAbsolute(params); +csiStateHandler['a'] = (handler, params, prefix) => handler.HPositionRelative(params); +csiStateHandler['b'] = (handler, params, prefix) => handler.repeatPrecedingCharacter(params); +csiStateHandler['c'] = (handler, params, prefix) => handler.sendDeviceAttributes(params); +csiStateHandler['d'] = (handler, params, prefix) => handler.linePosAbsolute(params); +csiStateHandler['e'] = (handler, params, prefix) => handler.VPositionRelative(params); +csiStateHandler['f'] = (handler, params, prefix) => handler.HVPosition(params); +csiStateHandler['g'] = (handler, params, prefix) => handler.tabClear(params); +csiStateHandler['h'] = (handler, params, prefix) => handler.setMode(params); +csiStateHandler['l'] = (handler, params, prefix) => handler.resetMode(params); +csiStateHandler['m'] = (handler, params, prefix) => handler.charAttributes(params); +csiStateHandler['n'] = (handler, params, prefix) => handler.deviceStatus(params); +csiStateHandler['p'] = (handler, params, prefix) => { + switch (prefix) { + case '!': handler.softReset(params); break; + } +}; +csiStateHandler['q'] = (handler, params, prefix, postfix) => { + if (postfix === ' ') { + handler.setCursorStyle(params); + } +}; +csiStateHandler['r'] = (handler, params) => handler.setScrollRegion(params); +csiStateHandler['s'] = (handler, params) => handler.saveCursor(params); +csiStateHandler['u'] = (handler, params) => handler.restoreCursor(params); +csiStateHandler[C0.CAN] = (handler, params, prefix, postfix, parser) => parser.setState(ParserState.NORMAL); + +export enum ParserState { + NORMAL = 0, + ESCAPED = 1, + CSI_PARAM = 2, + CSI = 3, + OSC = 4, + CHARSET = 5, + DCS = 6, + IGNORE = 7 +} + +/** + * The terminal's parser, all input into the terminal goes through the parser + * which parses and defers the actual input handling the the IInputHandler + * specified in the constructor. + */ +export class Parser { + private _state: ParserState; + private _position: number; + + // TODO: Remove terminal when handler can do everything + constructor( + private _inputHandler: IInputHandler, + private _terminal: any + ) { + this._state = ParserState.NORMAL; + } + + /** + * Parse and handle data. + * + * @param data The data to parse. + */ + public parse(data: string): ParserState { + const l = data.length; + let j; + let cs; + let ch; + let code; + let low; + + const cursorStartX = this._terminal.buffer.x; + const cursorStartY = this._terminal.buffer.y; + + if (this._terminal.debug) { + this._terminal.log('data: ' + data); + } + + this._position = 0; + // apply leftover surrogate high from last write + if (this._terminal.surrogate_high) { + data = this._terminal.surrogate_high + data; + this._terminal.surrogate_high = ''; + } + + for (; this._position < l; this._position++) { + ch = data[this._position]; + + // FIXME: higher chars than 0xa0 are not allowed in escape sequences + // --> maybe move to default + code = data.charCodeAt(this._position); + if (0xD800 <= code && code <= 0xDBFF) { + // we got a surrogate high + // get surrogate low (next 2 bytes) + low = data.charCodeAt(this._position + 1); + if (isNaN(low)) { + // end of data stream, save surrogate high + this._terminal.surrogate_high = ch; + continue; + } + code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000; + ch += data.charAt(this._position + 1); + } + // surrogate low - already handled above + if (0xDC00 <= code && code <= 0xDFFF) + continue; + + switch (this._state) { + case ParserState.NORMAL: + if (ch in normalStateHandler) { + normalStateHandler[ch](this, this._inputHandler); + } else { + this._inputHandler.addChar(ch, code); + } + break; + case ParserState.ESCAPED: + if (ch in escapedStateHandler) { + escapedStateHandler[ch](this, this._terminal); + // Skip switch as it was just handled + break; + } + switch (ch) { + + // ESC (,),*,+,-,. Designate G0-G2 Character Set. + case '(': // <-- this seems to get all the attention + case ')': + case '*': + case '+': + case '-': + case '.': + switch (ch) { + case '(': + this._terminal.gcharset = 0; + break; + case ')': + this._terminal.gcharset = 1; + break; + case '*': + this._terminal.gcharset = 2; + break; + case '+': + this._terminal.gcharset = 3; + break; + case '-': + this._terminal.gcharset = 1; + break; + case '.': + this._terminal.gcharset = 2; + break; + } + this._state = ParserState.CHARSET; + break; + + // Designate G3 Character Set (VT300). + // A = ISO Latin-1 Supplemental. + // Not implemented. + case '/': + this._terminal.gcharset = 3; + this._state = ParserState.CHARSET; + this._position--; + break; + + // ESC N + // Single Shift Select of G2 Character Set + // ( SS2 is 0x8e). This affects next character only. + case 'N': + this._state = ParserState.NORMAL; + break; + // ESC O + // Single Shift Select of G3 Character Set + // ( SS3 is 0x8f). This affects next character only. + case 'O': + this._state = ParserState.NORMAL; + break; + // ESC n + // Invoke the G2 Character Set as GL (LS2). + case 'n': + this._terminal.setgLevel(2); + this._state = ParserState.NORMAL; + break; + // ESC o + // Invoke the G3 Character Set as GL (LS3). + case 'o': + this._terminal.setgLevel(3); + this._state = ParserState.NORMAL; + break; + // ESC | + // Invoke the G3 Character Set as GR (LS3R). + case '|': + this._terminal.setgLevel(3); + this._state = ParserState.NORMAL; + break; + // ESC } + // Invoke the G2 Character Set as GR (LS2R). + case '}': + this._terminal.setgLevel(2); + this._state = ParserState.NORMAL; + break; + // ESC ~ + // Invoke the G1 Character Set as GR (LS1R). + case '~': + this._terminal.setgLevel(1); + this._state = ParserState.NORMAL; + break; + + // ESC 7 Save Cursor (DECSC). + case '7': + this._inputHandler.saveCursor(); + this._state = ParserState.NORMAL; + break; + + // ESC 8 Restore Cursor (DECRC). + case '8': + this._inputHandler.restoreCursor(); + this._state = ParserState.NORMAL; + break; + + // ESC # 3 DEC line height/width + case '#': + this._state = ParserState.NORMAL; + this._position++; + break; + + // ESC H Tab Set (HTS is 0x88). + case 'H': + this._terminal.tabSet(); + this._state = ParserState.NORMAL; + break; + + // ESC = Application Keypad (DECKPAM). + case '=': + this._terminal.log('Serial port requested application keypad.'); + this._terminal.applicationKeypad = true; + if (this._terminal.viewport) { + this._terminal.viewport.syncScrollArea(); + } + this._state = ParserState.NORMAL; + break; + + // ESC > Normal Keypad (DECKPNM). + case '>': + this._terminal.log('Switching back to normal keypad.'); + this._terminal.applicationKeypad = false; + if (this._terminal.viewport) { + this._terminal.viewport.syncScrollArea(); + } + this._state = ParserState.NORMAL; + break; + + default: + this._state = ParserState.NORMAL; + this._terminal.error('Unknown ESC control: %s.', ch); + break; + } + break; + + case ParserState.CHARSET: + if (ch in CHARSETS) { + cs = CHARSETS[ch]; + if (ch === '/') { // ISOLatin is actually /A + this.skipNextChar(); + } + } else { + cs = DEFAULT_CHARSET; + } + this._terminal.setgCharset(this._terminal.gcharset, cs); + this._terminal.gcharset = null; + this._state = ParserState.NORMAL; + break; + + case ParserState.OSC: + // OSC Ps ; Pt ST + // OSC Ps ; Pt BEL + // Set Text Parameters. + if (ch === C0.ESC || ch === C0.BEL) { + if (ch === C0.ESC) this._position++; + + this._terminal.params.push(this._terminal.currentParam); + + switch (this._terminal.params[0]) { + case 0: + case 1: + case 2: + if (this._terminal.params[1]) { + this._terminal.title = this._terminal.params[1]; + this._terminal.handleTitle(this._terminal.title); + } + break; + case 3: + // set X property + break; + case 4: + case 5: + // change dynamic colors + break; + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + // change dynamic ui colors + break; + case 46: + // change log file + break; + case 50: + // dynamic font + break; + case 51: + // emacs shell + break; + case 52: + // manipulate selection data + break; + case 104: + case 105: + case 110: + case 111: + case 112: + case 113: + case 114: + case 115: + case 116: + case 117: + case 118: + // reset colors + break; + } + + this._terminal.params = []; + this._terminal.currentParam = 0; + this._state = ParserState.NORMAL; + } else { + if (!this._terminal.params.length) { + if (ch >= '0' && ch <= '9') { + this._terminal.currentParam = + this._terminal.currentParam * 10 + ch.charCodeAt(0) - 48; + } else if (ch === ';') { + this._terminal.params.push(this._terminal.currentParam); + this._terminal.currentParam = ''; + } + } else { + this._terminal.currentParam += ch; + } + } + break; + + case ParserState.CSI_PARAM: + if (ch in csiParamStateHandler) { + csiParamStateHandler[ch](this); + break; + } + this.finalizeParam(); + // Fall through the CSI as this character should be the CSI code. + this._state = ParserState.CSI; + + case ParserState.CSI: + if (ch in csiStateHandler) { + if (this._terminal.debug) { + this._terminal.log(`CSI ${this._terminal.prefix ? this._terminal.prefix : ''} ${this._terminal.params ? this._terminal.params.join(';') : ''} ${this._terminal.postfix ? this._terminal.postfix : ''} ${ch}`); + } + csiStateHandler[ch](this._inputHandler, this._terminal.params, this._terminal.prefix, this._terminal.postfix, this); + } else { + this._terminal.error('Unknown CSI code: %s.', ch); + } + + this._state = ParserState.NORMAL; + this._terminal.prefix = ''; + this._terminal.postfix = ''; + break; + + case ParserState.DCS: + if (ch === C0.ESC || ch === C0.BEL) { + if (ch === C0.ESC) this._position++; + let pt; + let valid: boolean; + + switch (this._terminal.prefix) { + // User-Defined Keys (DECUDK). + case '': + break; + + // Request Status String (DECRQSS). + // test: echo -e '\eP$q"p\e\\' + case '$q': + pt = this._terminal.currentParam; + valid = false; + + switch (pt) { + // DECSCA + case '"q': + pt = '0"q'; + break; + + // DECSCL + case '"p': + pt = '61"p'; + break; + + // DECSTBM + case 'r': + pt = '' + + (this._terminal.buffer.scrollTop + 1) + + ';' + + (this._terminal.buffer.scrollBottom + 1) + + 'r'; + break; + + // SGR + case 'm': + pt = '0m'; + break; + + default: + this._terminal.error('Unknown DCS Pt: %s.', pt); + pt = ''; + break; + } + + this._terminal.send(C0.ESC + 'P' + +valid + '$r' + pt + C0.ESC + '\\'); + break; + + // Set Termcap/Terminfo Data (xterm, experimental). + case '+p': + break; + + // Request Termcap/Terminfo String (xterm, experimental) + // Regular xterm does not even respond to this sequence. + // This can cause a small glitch in vim. + // test: echo -ne '\eP+q6b64\e\\' + case '+q': + pt = this._terminal.currentParam; + valid = false; + + this._terminal.send(C0.ESC + 'P' + +valid + '+r' + pt + C0.ESC + '\\'); + break; + + default: + this._terminal.error('Unknown DCS prefix: %s.', this._terminal.prefix); + break; + } + + this._terminal.currentParam = 0; + this._terminal.prefix = ''; + this._state = ParserState.NORMAL; + } else if (!this._terminal.currentParam) { + if (!this._terminal.prefix && ch !== '$' && ch !== '+') { + this._terminal.currentParam = ch; + } else if (this._terminal.prefix.length === 2) { + this._terminal.currentParam = ch; + } else { + this._terminal.prefix += ch; + } + } else { + this._terminal.currentParam += ch; + } + break; + + case ParserState.IGNORE: + // For PM and APC. + if (ch === C0.ESC || ch === C0.BEL) { + if (ch === C0.ESC) this._position++; + this._state = ParserState.NORMAL; + } + break; + } + } + + // Fire the cursormove event if it's moved. This is done inside the parser + // as a render cannot happen in the middle of a parsing round. + if (this._terminal.buffer.x !== cursorStartX || this._terminal.buffer.y !== cursorStartY) { + this._terminal.emit('cursormove'); + } + + return this._state; + } + + /** + * Set the parser's current parsing state. + * + * @param state The new state. + */ + public setState(state: ParserState): void { + this._state = state; + } + + /** + * Sets the parsier's current prefix. CSI codes can have prefixes of '?', '>' + * or '!'. + * + * @param prefix The prefix. + */ + public setPrefix(prefix: string): void { + this._terminal.prefix = prefix; + } + + /** + * Sets the parsier's current prefix. CSI codes can have postfixes of '$', + * '"', ' ', '\''. + * + * @param postfix The postfix. + */ + public setPostfix(postfix: string): void { + this._terminal.postfix = postfix; + } + + /** + * Sets the parser's current parameter. + * + * @param param the parameter. + */ + public setParam(param: number): void { + this._terminal.currentParam = param; + } + + /** + * Gets the parser's current parameter. + */ + public getParam(): number { + return this._terminal.currentParam; + } + + /** + * Finalizes the parser's current parameter, adding it to the list of + * parameters and setting the new current parameter to 0. + */ + public finalizeParam(): void { + this._terminal.params.push(this._terminal.currentParam); + this._terminal.currentParam = 0; + } + + /** + * Tell the parser to skip the next character. + */ + public skipNextChar(): void { + this._position++; + } + + /** + * Tell the parser to repeat parsing the current character (for example if it + * needs parsing using a different state. + */ + // public repeatChar(): void { + // this._position--; + // } +} diff --git a/xterm.js/src/SelectionManager.test.ts b/xterm.js/src/SelectionManager.test.ts new file mode 100644 index 0000000..a10dc66 --- /dev/null +++ b/xterm.js/src/SelectionManager.test.ts @@ -0,0 +1,344 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import jsdom = require('jsdom'); +import { assert } from 'chai'; +import { ITerminal, ICircularList, IBuffer } from './Interfaces'; +import { CharMeasure } from './utils/CharMeasure'; +import { CircularList } from './utils/CircularList'; +import { SelectionManager } from './SelectionManager'; +import { SelectionModel } from './SelectionModel'; +import { BufferSet } from './BufferSet'; +import { MockTerminal } from './utils/TestUtils.test'; +import { LineData, CharData } from './Types'; + +class TestMockTerminal extends MockTerminal { + emit(event: string, data: any): void {} +} + +class TestSelectionManager extends SelectionManager { + constructor( + terminal: ITerminal, + buffer: IBuffer, + charMeasure: CharMeasure + ) { + super(terminal, buffer, charMeasure); + } + + public get model(): SelectionModel { return this._model; } + + public selectLineAt(line: number): void { this._selectLineAt(line); } + public selectWordAt(coords: [number, number]): void { this._selectWordAt(coords); } + + // Disable DOM interaction + public enable(): void {} + public disable(): void {} + public refresh(): void {} +} + +describe('SelectionManager', () => { + let dom: jsdom.JSDOM; + let window: Window; + let document: Document; + + let terminal: ITerminal; + let buffer: IBuffer; + let rowContainer: HTMLElement; + let selectionManager: TestSelectionManager; + + beforeEach(() => { + dom = new jsdom.JSDOM(''); + window = dom.window; + document = window.document; + terminal = new TestMockTerminal(); + terminal.cols = 80; + terminal.rows = 2; + terminal.options.scrollback = 100; + terminal.buffers = new BufferSet(terminal); + terminal.buffer = terminal.buffers.active; + buffer = terminal.buffer; + selectionManager = new TestSelectionManager(terminal, buffer, null); + }); + + function stringToRow(text: string): LineData { + let result: LineData = []; + for (let i = 0; i < text.length; i++) { + result.push([0, text.charAt(i), 1, text.charCodeAt(i)]); + } + return result; + } + + function stringArrayToRow(chars: string[]): LineData { + return chars.map(c => [0, c, 1, c.charCodeAt(0)]); + } + + describe('_selectWordAt', () => { + it('should expand selection for normal width chars', () => { + buffer.lines.set(0, stringToRow('foo bar')); + selectionManager.selectWordAt([0, 0]); + assert.equal(selectionManager.selectionText, 'foo'); + selectionManager.selectWordAt([1, 0]); + assert.equal(selectionManager.selectionText, 'foo'); + selectionManager.selectWordAt([2, 0]); + assert.equal(selectionManager.selectionText, 'foo'); + selectionManager.selectWordAt([3, 0]); + assert.equal(selectionManager.selectionText, ' '); + selectionManager.selectWordAt([4, 0]); + assert.equal(selectionManager.selectionText, 'bar'); + selectionManager.selectWordAt([5, 0]); + assert.equal(selectionManager.selectionText, 'bar'); + selectionManager.selectWordAt([6, 0]); + assert.equal(selectionManager.selectionText, 'bar'); + }); + it('should expand selection for whitespace', () => { + buffer.lines.set(0, stringToRow('a b')); + selectionManager.selectWordAt([0, 0]); + assert.equal(selectionManager.selectionText, 'a'); + selectionManager.selectWordAt([1, 0]); + assert.equal(selectionManager.selectionText, ' '); + selectionManager.selectWordAt([2, 0]); + assert.equal(selectionManager.selectionText, ' '); + selectionManager.selectWordAt([3, 0]); + assert.equal(selectionManager.selectionText, ' '); + selectionManager.selectWordAt([4, 0]); + assert.equal(selectionManager.selectionText, 'b'); + }); + it('should expand selection for wide characters', () => { + // Wide characters use a special format + buffer.lines.set(0, [ + [null, '中', 2, '中'.charCodeAt(0)], + [null, '', 0, null], + [null, '文', 2, '文'.charCodeAt(0)], + [null, '', 0, null], + [null, ' ', 1, ' '.charCodeAt(0)], + [null, 'a', 1, 'a'.charCodeAt(0)], + [null, '中', 2, '中'.charCodeAt(0)], + [null, '', 0, null], + [null, '文', 2, '文'.charCodeAt(0)], + [null, '', 0, ''.charCodeAt(0)], + [null, 'b', 1, 'b'.charCodeAt(0)], + [null, ' ', 1, ' '.charCodeAt(0)], + [null, 'f', 1, 'f'.charCodeAt(0)], + [null, 'o', 1, 'o'.charCodeAt(0)], + [null, 'o', 1, 'o'.charCodeAt(0)] + ]); + // Ensure wide characters take up 2 columns + selectionManager.selectWordAt([0, 0]); + assert.equal(selectionManager.selectionText, '中文'); + selectionManager.selectWordAt([1, 0]); + assert.equal(selectionManager.selectionText, '中文'); + selectionManager.selectWordAt([2, 0]); + assert.equal(selectionManager.selectionText, '中文'); + selectionManager.selectWordAt([3, 0]); + assert.equal(selectionManager.selectionText, '中文'); + selectionManager.selectWordAt([4, 0]); + assert.equal(selectionManager.selectionText, ' '); + // Ensure wide characters work when wrapped in normal width characters + selectionManager.selectWordAt([5, 0]); + assert.equal(selectionManager.selectionText, 'a中文b'); + selectionManager.selectWordAt([6, 0]); + assert.equal(selectionManager.selectionText, 'a中文b'); + selectionManager.selectWordAt([7, 0]); + assert.equal(selectionManager.selectionText, 'a中文b'); + selectionManager.selectWordAt([8, 0]); + assert.equal(selectionManager.selectionText, 'a中文b'); + selectionManager.selectWordAt([9, 0]); + assert.equal(selectionManager.selectionText, 'a中文b'); + selectionManager.selectWordAt([10, 0]); + assert.equal(selectionManager.selectionText, 'a中文b'); + selectionManager.selectWordAt([11, 0]); + assert.equal(selectionManager.selectionText, ' '); + // Ensure normal width characters work fine in a line containing wide characters + selectionManager.selectWordAt([12, 0]); + assert.equal(selectionManager.selectionText, 'foo'); + selectionManager.selectWordAt([13, 0]); + assert.equal(selectionManager.selectionText, 'foo'); + selectionManager.selectWordAt([14, 0]); + assert.equal(selectionManager.selectionText, 'foo'); + }); + it('should select up to non-path characters that are commonly adjacent to paths', () => { + buffer.lines.set(0, stringToRow('(cd)[ef]{gh}\'ij"')); + selectionManager.selectWordAt([0, 0]); + assert.equal(selectionManager.selectionText, '(cd'); + selectionManager.selectWordAt([1, 0]); + assert.equal(selectionManager.selectionText, 'cd'); + selectionManager.selectWordAt([2, 0]); + assert.equal(selectionManager.selectionText, 'cd'); + selectionManager.selectWordAt([3, 0]); + assert.equal(selectionManager.selectionText, 'cd)'); + selectionManager.selectWordAt([4, 0]); + assert.equal(selectionManager.selectionText, '[ef'); + selectionManager.selectWordAt([5, 0]); + assert.equal(selectionManager.selectionText, 'ef'); + selectionManager.selectWordAt([6, 0]); + assert.equal(selectionManager.selectionText, 'ef'); + selectionManager.selectWordAt([7, 0]); + assert.equal(selectionManager.selectionText, 'ef]'); + selectionManager.selectWordAt([8, 0]); + assert.equal(selectionManager.selectionText, '{gh'); + selectionManager.selectWordAt([9, 0]); + assert.equal(selectionManager.selectionText, 'gh'); + selectionManager.selectWordAt([10, 0]); + assert.equal(selectionManager.selectionText, 'gh'); + selectionManager.selectWordAt([11, 0]); + assert.equal(selectionManager.selectionText, 'gh}'); + selectionManager.selectWordAt([12, 0]); + assert.equal(selectionManager.selectionText, '\'ij'); + selectionManager.selectWordAt([13, 0]); + assert.equal(selectionManager.selectionText, 'ij'); + selectionManager.selectWordAt([14, 0]); + assert.equal(selectionManager.selectionText, 'ij'); + selectionManager.selectWordAt([15, 0]); + assert.equal(selectionManager.selectionText, 'ij"'); + }); + describe('emoji', () => { + it('should treat a single emoji as a word when wrapped in spaces', () => { + buffer.lines.set(0, stringToRow(' ⚽ a')); // The a is here to prevent the space being trimmed in selectionText + selectionManager.selectWordAt([0, 0]); + assert.equal(selectionManager.selectionText, ' '); + selectionManager.selectWordAt([1, 0]); + assert.equal(selectionManager.selectionText, '⚽'); + selectionManager.selectWordAt([2, 0]); + assert.equal(selectionManager.selectionText, ' '); + }); + it('should treat multiple emojis as a word when wrapped in spaces', () => { + buffer.lines.set(0, stringToRow(' ⚽⚽ a')); // The a is here to prevent the space being trimmed in selectionText + selectionManager.selectWordAt([0, 0]); + assert.equal(selectionManager.selectionText, ' '); + selectionManager.selectWordAt([1, 0]); + assert.equal(selectionManager.selectionText, '⚽⚽'); + selectionManager.selectWordAt([2, 0]); + assert.equal(selectionManager.selectionText, '⚽⚽'); + selectionManager.selectWordAt([3, 0]); + assert.equal(selectionManager.selectionText, ' '); + }); + it('should treat emojis using the zero-width-joiner as a single word', () => { + // Note that the first 3 emojis include the invisible ZWJ char + buffer.lines.set(0, stringArrayToRow([ + ' ', '👨‍', '👩‍', '👧‍', '👦', ' ', 'a' + ])); // The a is here to prevent the space being trimmed in selectionText + selectionManager.selectWordAt([0, 0]); + assert.equal(selectionManager.selectionText, ' '); + // ZWJ emojis do not combine in the terminal so the family emoji used here consumed 4 cells + // The selection text should retain ZWJ chars despite not combining on the terminal + selectionManager.selectWordAt([1, 0]); + assert.equal(selectionManager.selectionText, '👨‍👩‍👧‍👦'); + selectionManager.selectWordAt([2, 0]); + assert.equal(selectionManager.selectionText, '👨‍👩‍👧‍👦'); + selectionManager.selectWordAt([3, 0]); + assert.equal(selectionManager.selectionText, '👨‍👩‍👧‍👦'); + selectionManager.selectWordAt([4, 0]); + assert.equal(selectionManager.selectionText, '👨‍👩‍👧‍👦'); + selectionManager.selectWordAt([5, 0]); + assert.equal(selectionManager.selectionText, ' '); + }); + it('should treat emojis and characters joined together as a word', () => { + buffer.lines.set(0, stringToRow(' ⚽ab cd⚽ ef⚽gh')); // The a is here to prevent the space being trimmed in selectionText + selectionManager.selectWordAt([0, 0]); + assert.equal(selectionManager.selectionText, ' '); + selectionManager.selectWordAt([1, 0]); + assert.equal(selectionManager.selectionText, '⚽ab'); + selectionManager.selectWordAt([2, 0]); + assert.equal(selectionManager.selectionText, '⚽ab'); + selectionManager.selectWordAt([3, 0]); + assert.equal(selectionManager.selectionText, '⚽ab'); + selectionManager.selectWordAt([4, 0]); + assert.equal(selectionManager.selectionText, ' '); + selectionManager.selectWordAt([5, 0]); + assert.equal(selectionManager.selectionText, 'cd⚽'); + selectionManager.selectWordAt([6, 0]); + assert.equal(selectionManager.selectionText, 'cd⚽'); + selectionManager.selectWordAt([7, 0]); + assert.equal(selectionManager.selectionText, 'cd⚽'); + selectionManager.selectWordAt([8, 0]); + assert.equal(selectionManager.selectionText, ' '); + selectionManager.selectWordAt([9, 0]); + assert.equal(selectionManager.selectionText, 'ef⚽gh'); + selectionManager.selectWordAt([10, 0]); + assert.equal(selectionManager.selectionText, 'ef⚽gh'); + selectionManager.selectWordAt([11, 0]); + assert.equal(selectionManager.selectionText, 'ef⚽gh'); + selectionManager.selectWordAt([12, 0]); + assert.equal(selectionManager.selectionText, 'ef⚽gh'); + selectionManager.selectWordAt([13, 0]); + assert.equal(selectionManager.selectionText, 'ef⚽gh'); + }); + it('should treat complex emojis and characters joined together as a word', () => { + // This emoji is the flag for England and is made up of: 1F3F4 E0067 E0062 E0065 E006E E0067 E007F + buffer.lines.set(0, stringArrayToRow([ + ' ', '🏴󠁧󠁢󠁥󠁮󠁧󠁿', 'a', 'b', ' ', 'c', 'd', '🏴󠁧󠁢󠁥󠁮󠁧󠁿', ' ', 'e', 'f', '🏴󠁧󠁢󠁥󠁮󠁧󠁿', 'g', 'h', ' ', 'a' + ])); // The a is here to prevent the space being trimmed in selectionText + selectionManager.selectWordAt([0, 0]); + assert.equal(selectionManager.selectionText, ' '); + selectionManager.selectWordAt([1, 0]); + assert.equal(selectionManager.selectionText, '🏴󠁧󠁢󠁥󠁮󠁧󠁿ab'); + selectionManager.selectWordAt([2, 0]); + assert.equal(selectionManager.selectionText, '🏴󠁧󠁢󠁥󠁮󠁧󠁿ab'); + selectionManager.selectWordAt([3, 0]); + assert.equal(selectionManager.selectionText, '🏴󠁧󠁢󠁥󠁮󠁧󠁿ab'); + selectionManager.selectWordAt([4, 0]); + assert.equal(selectionManager.selectionText, ' '); + selectionManager.selectWordAt([5, 0]); + assert.equal(selectionManager.selectionText, 'cd🏴󠁧󠁢󠁥󠁮󠁧󠁿'); + selectionManager.selectWordAt([6, 0]); + assert.equal(selectionManager.selectionText, 'cd🏴󠁧󠁢󠁥󠁮󠁧󠁿'); + selectionManager.selectWordAt([7, 0]); + assert.equal(selectionManager.selectionText, 'cd🏴󠁧󠁢󠁥󠁮󠁧󠁿'); + selectionManager.selectWordAt([8, 0]); + assert.equal(selectionManager.selectionText, ' '); + selectionManager.selectWordAt([9, 0]); + assert.equal(selectionManager.selectionText, 'ef🏴󠁧󠁢󠁥󠁮󠁧󠁿gh'); + selectionManager.selectWordAt([10, 0]); + assert.equal(selectionManager.selectionText, 'ef🏴󠁧󠁢󠁥󠁮󠁧󠁿gh'); + selectionManager.selectWordAt([11, 0]); + assert.equal(selectionManager.selectionText, 'ef🏴󠁧󠁢󠁥󠁮󠁧󠁿gh'); + selectionManager.selectWordAt([12, 0]); + assert.equal(selectionManager.selectionText, 'ef🏴󠁧󠁢󠁥󠁮󠁧󠁿gh'); + selectionManager.selectWordAt([13, 0]); + assert.equal(selectionManager.selectionText, 'ef🏴󠁧󠁢󠁥󠁮󠁧󠁿gh'); + }); + }); + }); + + describe('_selectLineAt', () => { + it('should select the entire line', () => { + buffer.lines.set(0, stringToRow('foo bar')); + selectionManager.selectLineAt(0); + assert.equal(selectionManager.selectionText, 'foo bar', 'The selected text is correct'); + assert.deepEqual(selectionManager.model.finalSelectionStart, [0, 0]); + assert.deepEqual(selectionManager.model.finalSelectionEnd, [terminal.cols, 0], 'The actual selection spans the entire column'); + }); + }); + + describe('selectAll', () => { + it('should select the entire buffer, beyond the viewport', () => { + buffer.lines.length = 5; + buffer.lines.set(0, stringToRow('1')); + buffer.lines.set(1, stringToRow('2')); + buffer.lines.set(2, stringToRow('3')); + buffer.lines.set(3, stringToRow('4')); + buffer.lines.set(4, stringToRow('5')); + selectionManager.selectAll(); + terminal.buffer.ybase = buffer.lines.length - terminal.rows; + assert.equal(selectionManager.selectionText, '1\n2\n3\n4\n5'); + }); + }); + + describe('hasSelection', () => { + it('should return whether there is a selection', () => { + selectionManager.model.selectionStart = [0, 0]; + selectionManager.model.selectionStartLength = 0; + assert.equal(selectionManager.hasSelection, false); + selectionManager.model.selectionEnd = [0, 0]; + assert.equal(selectionManager.hasSelection, false); + selectionManager.model.selectionEnd = [1, 0]; + assert.equal(selectionManager.hasSelection, true); + selectionManager.model.selectionEnd = [0, 1]; + assert.equal(selectionManager.hasSelection, true); + selectionManager.model.selectionEnd = [1, 1]; + assert.equal(selectionManager.hasSelection, true); + }); + }); +}); diff --git a/xterm.js/src/SelectionManager.ts b/xterm.js/src/SelectionManager.ts new file mode 100644 index 0000000..cd6fc99 --- /dev/null +++ b/xterm.js/src/SelectionManager.ts @@ -0,0 +1,739 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { MouseHelper } from './utils/MouseHelper'; +import * as Browser from './utils/Browser'; +import { CharMeasure } from './utils/CharMeasure'; +import { CircularList } from './utils/CircularList'; +import { EventEmitter } from './EventEmitter'; +import { ITerminal, ICircularList, ISelectionManager, IBuffer } from './Interfaces'; +import { SelectionModel } from './SelectionModel'; +import { LineData, CharData } from './Types'; +import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from './Buffer'; + +/** + * The number of pixels the mouse needs to be above or below the viewport in + * order to scroll at the maximum speed. + */ +const DRAG_SCROLL_MAX_THRESHOLD = 50; + +/** + * The maximum scrolling speed + */ +const DRAG_SCROLL_MAX_SPEED = 15; + +/** + * The number of milliseconds between drag scroll updates. + */ +const DRAG_SCROLL_INTERVAL = 50; + +/** + * A string containing all characters that are considered word separated by the + * double click to select work logic. + */ +const WORD_SEPARATORS = ' ()[]{}\'"'; + +const NON_BREAKING_SPACE_CHAR = String.fromCharCode(160); +const ALL_NON_BREAKING_SPACE_REGEX = new RegExp(NON_BREAKING_SPACE_CHAR, 'g'); + +/** + * Represents a position of a word on a line. + */ +interface IWordPosition { + start: number; + length: number; +} + +/** + * A selection mode, this drives how the selection behaves on mouse move. + */ +enum SelectionMode { + NORMAL, + WORD, + LINE +} + +/** + * A class that manages the selection of the terminal. With help from + * SelectionModel, SelectionManager handles with all logic associated with + * dealing with the selection, including handling mouse interaction, wide + * characters and fetching the actual text within the selection. Rendering is + * not handled by the SelectionManager but a 'refresh' event is fired when the + * selection is ready to be redrawn. + */ +export class SelectionManager extends EventEmitter implements ISelectionManager { + protected _model: SelectionModel; + + /** + * The amount to scroll every drag scroll update (depends on how far the mouse + * drag is above or below the terminal). + */ + private _dragScrollAmount: number; + + /** + * The current selection mode. + */ + private _activeSelectionMode: SelectionMode; + + /** + * A setInterval timer that is active while the mouse is down whose callback + * scrolls the viewport when necessary. + */ + private _dragScrollIntervalTimer: NodeJS.Timer; + + /** + * The animation frame ID used for refreshing the selection. + */ + private _refreshAnimationFrame: number; + + /** + * Whether selection is enabled. + */ + private _enabled = true; + + private _mouseMoveListener: EventListener; + private _mouseUpListener: EventListener; + + constructor( + private _terminal: ITerminal, + private _buffer: IBuffer, + private _charMeasure: CharMeasure + ) { + super(); + this._initListeners(); + this.enable(); + + this._model = new SelectionModel(_terminal); + this._activeSelectionMode = SelectionMode.NORMAL; + } + + /** + * Initializes listener variables. + */ + private _initListeners(): void { + this._mouseMoveListener = event => this._onMouseMove(event); + this._mouseUpListener = event => this._onMouseUp(event); + + // Only adjust the selection on trim, shiftElements is rarely used (only in + // reverseIndex) and delete in a splice is only ever used when the same + // number of elements was just added. Given this is could actually be + // beneficial to leave the selection as is for these cases. + this._buffer.lines.on('trim', (amount: number) => this._onTrim(amount)); + } + + /** + * Disables the selection manager. This is useful for when terminal mouse + * are enabled. + */ + public disable(): void { + this.clearSelection(); + this._enabled = false; + } + + /** + * Enable the selection manager. + */ + public enable(): void { + this._enabled = true; + } + + /** + * Sets the active buffer, this should be called when the alt buffer is + * switched in or out. + * @param buffer The active buffer. + */ + public setBuffer(buffer: IBuffer): void { + this._buffer = buffer; + this.clearSelection(); + } + + public get selectionStart(): [number, number] { return this._model.finalSelectionStart; } + public get selectionEnd(): [number, number] { return this._model.finalSelectionEnd; } + + /** + * Gets whether there is an active text selection. + */ + public get hasSelection(): boolean { + const start = this._model.finalSelectionStart; + const end = this._model.finalSelectionEnd; + if (!start || !end) { + return false; + } + return start[0] !== end[0] || start[1] !== end[1]; + } + + /** + * Gets the text currently selected. + */ + public get selectionText(): string { + const start = this._model.finalSelectionStart; + const end = this._model.finalSelectionEnd; + if (!start || !end) { + return ''; + } + + // Get first row + const startRowEndCol = start[1] === end[1] ? end[0] : null; + let result: string[] = []; + result.push(this._buffer.translateBufferLineToString(start[1], true, start[0], startRowEndCol)); + + // Get middle rows + for (let i = start[1] + 1; i <= end[1] - 1; i++) { + const bufferLine = this._buffer.lines.get(i); + const lineText = this._buffer.translateBufferLineToString(i, true); + if ((bufferLine).isWrapped) { + result[result.length - 1] += lineText; + } else { + result.push(lineText); + } + } + + // Get final row + if (start[1] !== end[1]) { + const bufferLine = this._buffer.lines.get(end[1]); + const lineText = this._buffer.translateBufferLineToString(end[1], true, 0, end[0]); + if ((bufferLine).isWrapped) { + result[result.length - 1] += lineText; + } else { + result.push(lineText); + } + } + + // Format string by replacing non-breaking space chars with regular spaces + // and joining the array into a multi-line string. + const formattedResult = result.map(line => { + return line.replace(ALL_NON_BREAKING_SPACE_REGEX, ' '); + }).join(Browser.isMSWindows ? '\r\n' : '\n'); + + return formattedResult; + } + + /** + * Clears the current terminal selection. + */ + public clearSelection(): void { + this._model.clearSelection(); + this._removeMouseDownListeners(); + this.refresh(); + } + + /** + * Queues a refresh, redrawing the selection on the next opportunity. + * @param isNewSelection Whether the selection should be registered as a new + * selection on Linux. + */ + public refresh(isNewSelection?: boolean): void { + // Queue the refresh for the renderer + if (!this._refreshAnimationFrame) { + this._refreshAnimationFrame = window.requestAnimationFrame(() => this._refresh()); + } + + // If the platform is Linux and the refresh call comes from a mouse event, + // we need to update the selection for middle click to paste selection. + if (Browser.isLinux && isNewSelection) { + const selectionText = this.selectionText; + if (selectionText.length) { + this.emit('newselection', this.selectionText); + } + } + } + + /** + * Fires the refresh event, causing consumers to pick it up and redraw the + * selection state. + */ + private _refresh(): void { + this._refreshAnimationFrame = null; + this.emit('refresh', { start: this._model.finalSelectionStart, end: this._model.finalSelectionEnd }); + } + + /** + * Selects all text within the terminal. + */ + public selectAll(): void { + this._model.isSelectAllActive = true; + this.refresh(); + this._terminal.emit('selection'); + } + + /** + * Handle the buffer being trimmed, adjust the selection position. + * @param amount The amount the buffer is being trimmed. + */ + private _onTrim(amount: number): void { + const needsRefresh = this._model.onTrim(amount); + if (needsRefresh) { + this.refresh(); + } + } + + /** + * Gets the 0-based [x, y] buffer coordinates of the current mouse event. + * @param event The mouse event. + */ + private _getMouseBufferCoords(event: MouseEvent): [number, number] { + const coords = this._terminal.mouseHelper.getCoords(event, this._terminal.element, this._charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows, true); + if (!coords) { + return null; + } + + // Convert to 0-based + coords[0]--; + coords[1]--; + + // Convert viewport coords to buffer coords + coords[1] += this._terminal.buffer.ydisp; + return coords; + } + + /** + * Gets the amount the viewport should be scrolled based on how far out of the + * terminal the mouse is. + * @param event The mouse event. + */ + private _getMouseEventScrollAmount(event: MouseEvent): number { + let offset = MouseHelper.getCoordsRelativeToElement(event, this._terminal.element)[1]; + const terminalHeight = this._terminal.rows * Math.ceil(this._charMeasure.height * this._terminal.options.lineHeight); + if (offset >= 0 && offset <= terminalHeight) { + return 0; + } + if (offset > terminalHeight) { + offset -= terminalHeight; + } + + offset = Math.min(Math.max(offset, -DRAG_SCROLL_MAX_THRESHOLD), DRAG_SCROLL_MAX_THRESHOLD); + offset /= DRAG_SCROLL_MAX_THRESHOLD; + return (offset / Math.abs(offset)) + Math.round(offset * (DRAG_SCROLL_MAX_SPEED - 1)); + } + + /** + * Returns whether the selection manager should force selection, regardless of + * whether the terminal is in mouse events mode. + * @param event The mouse event. + */ + public shouldForceSelection(event: MouseEvent): boolean { + return Browser.isMac ? event.altKey : event.shiftKey; + } + + /** + * Handles te mousedown event, setting up for a new selection. + * @param event The mousedown event. + */ + public onMouseDown(event: MouseEvent): void { + // If we have selection, we want the context menu on right click even if the + // terminal is in mouse mode. + if (event.button === 2 && this.hasSelection) { + return; + } + + // Only action the primary button + if (event.button !== 0) { + return; + } + + // Allow selection when using a specific modifier key, even when disabled + if (!this._enabled) { + if (!this.shouldForceSelection(event)) { + return; + } + + // Don't send the mouse down event to the current process, we want to select + event.stopPropagation(); + } + + // Tell the browser not to start a regular selection + event.preventDefault(); + + // Reset drag scroll state + this._dragScrollAmount = 0; + + if (this._enabled && event.shiftKey) { + this._onIncrementalClick(event); + } else { + if (event.detail === 1) { + this._onSingleClick(event); + } else if (event.detail === 2) { + this._onDoubleClick(event); + } else if (event.detail === 3) { + this._onTripleClick(event); + } + } + + this._addMouseDownListeners(); + this.refresh(true); + } + + /** + * Adds listeners when mousedown is triggered. + */ + private _addMouseDownListeners(): void { + // Listen on the document so that dragging outside of viewport works + this._terminal.element.ownerDocument.addEventListener('mousemove', this._mouseMoveListener); + this._terminal.element.ownerDocument.addEventListener('mouseup', this._mouseUpListener); + this._dragScrollIntervalTimer = setInterval(() => this._dragScroll(), DRAG_SCROLL_INTERVAL); + } + + /** + * Removes the listeners that are registered when mousedown is triggered. + */ + private _removeMouseDownListeners(): void { + this._terminal.element.ownerDocument.removeEventListener('mousemove', this._mouseMoveListener); + this._terminal.element.ownerDocument.removeEventListener('mouseup', this._mouseUpListener); + clearInterval(this._dragScrollIntervalTimer); + this._dragScrollIntervalTimer = null; + } + + /** + * Performs an incremental click, setting the selection end position to the mouse + * position. + * @param event The mouse event. + */ + private _onIncrementalClick(event: MouseEvent): void { + if (this._model.selectionStart) { + this._model.selectionEnd = this._getMouseBufferCoords(event); + } + } + + /** + * Performs a single click, resetting relevant state and setting the selection + * start position. + * @param event The mouse event. + */ + private _onSingleClick(event: MouseEvent): void { + this._model.selectionStartLength = 0; + this._model.isSelectAllActive = false; + this._activeSelectionMode = SelectionMode.NORMAL; + + // Initialize the new selection + this._model.selectionStart = this._getMouseBufferCoords(event); + if (!this._model.selectionStart) { + return; + } + this._model.selectionEnd = null; + + // Ensure the line exists + const line = this._buffer.lines.get(this._model.selectionStart[1]); + if (!line) { + return; + } + + // Return early if the click event is not in the buffer (eg. in scroll bar) + if (line.length >= this._model.selectionStart[0]) { + return; + } + + // If the mouse is over the second half of a wide character, adjust the + // selection to cover the whole character + const char = line[this._model.selectionStart[0]]; + if (char[CHAR_DATA_WIDTH_INDEX] === 0) { + this._model.selectionStart[0]++; + } + } + + /** + * Performs a double click, selecting the current work. + * @param event The mouse event. + */ + private _onDoubleClick(event: MouseEvent): void { + const coords = this._getMouseBufferCoords(event); + if (coords) { + this._activeSelectionMode = SelectionMode.WORD; + this._selectWordAt(coords); + } + } + + /** + * Performs a triple click, selecting the current line and activating line + * select mode. + * @param event The mouse event. + */ + private _onTripleClick(event: MouseEvent): void { + const coords = this._getMouseBufferCoords(event); + if (coords) { + this._activeSelectionMode = SelectionMode.LINE; + this._selectLineAt(coords[1]); + } + } + + /** + * Handles the mousemove event when the mouse button is down, recording the + * end of the selection and refreshing the selection. + * @param event The mousemove event. + */ + private _onMouseMove(event: MouseEvent): void { + // If the mousemove listener is active it means that a selection is + // currently being made, we should stop propogation to prevent mouse events + // to be sent to the pty. + event.stopImmediatePropagation(); + + // Record the previous position so we know whether to redraw the selection + // at the end. + const previousSelectionEnd = this._model.selectionEnd ? [this._model.selectionEnd[0], this._model.selectionEnd[1]] : null; + + // Set the initial selection end based on the mouse coordinates + this._model.selectionEnd = this._getMouseBufferCoords(event); + if (!this._model.selectionEnd) { + this.refresh(true); + return; + } + + // Select the entire line if line select mode is active. + if (this._activeSelectionMode === SelectionMode.LINE) { + if (this._model.selectionEnd[1] < this._model.selectionStart[1]) { + this._model.selectionEnd[0] = 0; + } else { + this._model.selectionEnd[0] = this._terminal.cols; + } + } else if (this._activeSelectionMode === SelectionMode.WORD) { + this._selectToWordAt(this._model.selectionEnd); + } + + // Determine the amount of scrolling that will happen. + this._dragScrollAmount = this._getMouseEventScrollAmount(event); + + // If the cursor was above or below the viewport, make sure it's at the + // start or end of the viewport respectively. + if (this._dragScrollAmount > 0) { + this._model.selectionEnd[0] = this._terminal.cols; + } else if (this._dragScrollAmount < 0) { + this._model.selectionEnd[0] = 0; + } + + // If the character is a wide character include the cell to the right in the + // selection. Note that selections at the very end of the line will never + // have a character. + if (this._model.selectionEnd[1] < this._buffer.lines.length) { + const char = this._buffer.lines.get(this._model.selectionEnd[1])[this._model.selectionEnd[0]]; + if (char && char[CHAR_DATA_WIDTH_INDEX] === 0) { + this._model.selectionEnd[0]++; + } + } + + // Only draw here if the selection changes. + if (!previousSelectionEnd || + previousSelectionEnd[0] !== this._model.selectionEnd[0] || + previousSelectionEnd[1] !== this._model.selectionEnd[1]) { + this.refresh(true); + } + } + + /** + * The callback that occurs every DRAG_SCROLL_INTERVAL ms that does the + * scrolling of the viewport. + */ + private _dragScroll(): void { + if (this._dragScrollAmount) { + this._terminal.scrollLines(this._dragScrollAmount, false); + // Re-evaluate selection + if (this._dragScrollAmount > 0) { + this._model.selectionEnd = [this._terminal.cols - 1, Math.min(this._terminal.buffer.ydisp + this._terminal.rows, this._terminal.buffer.lines.length - 1)]; + } else { + this._model.selectionEnd = [0, this._terminal.buffer.ydisp]; + } + this.refresh(); + } + } + + /** + * Handles the mouseup event, removing the mousedown listeners. + * @param event The mouseup event. + */ + private _onMouseUp(event: MouseEvent): void { + this._removeMouseDownListeners(); + + if (this.hasSelection) + this._terminal.emit('selection'); + } + + /** + * Converts a viewport column to the character index on the buffer line, the + * latter takes into account wide characters. + * @param coords The coordinates to find the 2 index for. + */ + private _convertViewportColToCharacterIndex(bufferLine: any, coords: [number, number]): number { + let charIndex = coords[0]; + for (let i = 0; coords[0] >= i; i++) { + const char = bufferLine[i]; + if (char[CHAR_DATA_WIDTH_INDEX] === 0) { + // Wide characters aren't included in the line string so decrement the + // index so the index is back on the wide character. + charIndex--; + } else if (char[CHAR_DATA_CHAR_INDEX].length > 1 && coords[0] !== i) { + // Emojis take up multiple characters, so adjust accordingly. For these + // we don't want ot include the character at the column as we're + // returning the start index in the string, not the end index. + charIndex += char[CHAR_DATA_CHAR_INDEX].length - 1; + } + } + return charIndex; + } + + public setSelection(col: number, row: number, length: number): void { + this._model.clearSelection(); + this._removeMouseDownListeners(); + this._model.selectionStart = [col, row]; + this._model.selectionStartLength = length; + this.refresh(); + } + + /** + * Gets positional information for the word at the coordinated specified. + * @param coords The coordinates to get the word at. + */ + private _getWordAt(coords: [number, number]): IWordPosition { + const bufferLine = this._buffer.lines.get(coords[1]); + if (!bufferLine) { + return null; + } + + const line = this._buffer.translateBufferLineToString(coords[1], false); + + // Get actual index, taking into consideration wide characters + let startIndex = this._convertViewportColToCharacterIndex(bufferLine, coords); + let endIndex = startIndex; + + // Record offset to be used later + const charOffset = coords[0] - startIndex; + let leftWideCharCount = 0; + let rightWideCharCount = 0; + let leftLongCharOffset = 0; + let rightLongCharOffset = 0; + + if (line.charAt(startIndex) === ' ') { + // Expand until non-whitespace is hit + while (startIndex > 0 && line.charAt(startIndex - 1) === ' ') { + startIndex--; + } + while (endIndex < line.length && line.charAt(endIndex + 1) === ' ') { + endIndex++; + } + } else { + // Expand until whitespace is hit. This algorithm works by scanning left + // and right from the starting position, keeping both the index format + // (line) and the column format (bufferLine) in sync. When a wide + // character is hit, it is recorded and the column index is adjusted. + let startCol = coords[0]; + let endCol = coords[0]; + + // Consider the initial position, skip it and increment the wide char + // variable + if (bufferLine[startCol][CHAR_DATA_WIDTH_INDEX] === 0) { + leftWideCharCount++; + startCol--; + } + if (bufferLine[endCol][CHAR_DATA_WIDTH_INDEX] === 2) { + rightWideCharCount++; + endCol++; + } + + // Adjust the end index for characters whose length are > 1 (emojis) + if (bufferLine[endCol][CHAR_DATA_CHAR_INDEX].length > 1) { + rightLongCharOffset += bufferLine[endCol][CHAR_DATA_CHAR_INDEX].length - 1; + endIndex += bufferLine[endCol][CHAR_DATA_CHAR_INDEX].length - 1; + } + + // Expand the string in both directions until a space is hit + while (startCol > 0 && startIndex > 0 && !this._isCharWordSeparator(bufferLine[startCol - 1])) { + const char = bufferLine[startCol - 1]; + if (char[CHAR_DATA_WIDTH_INDEX] === 0) { + // If the next character is a wide char, record it and skip the column + leftWideCharCount++; + startCol--; + } else if (char[CHAR_DATA_CHAR_INDEX].length > 1) { + // If the next character's string is longer than 1 char (eg. emoji), + // adjust the index + leftLongCharOffset += char[CHAR_DATA_CHAR_INDEX].length - 1; + startIndex -= char[CHAR_DATA_CHAR_INDEX].length - 1; + } + startIndex--; + startCol--; + } + while (endCol < bufferLine.length && endIndex + 1 < line.length && !this._isCharWordSeparator(bufferLine[endCol + 1])) { + const char = bufferLine[endCol + 1]; + if (char[CHAR_DATA_WIDTH_INDEX] === 2) { + // If the next character is a wide char, record it and skip the column + rightWideCharCount++; + endCol++; + } else if (char[CHAR_DATA_CHAR_INDEX].length > 1) { + // If the next character's string is longer than 1 char (eg. emoji), + // adjust the index + rightLongCharOffset += char[CHAR_DATA_CHAR_INDEX].length - 1; + endIndex += char[CHAR_DATA_CHAR_INDEX].length - 1; + } + endIndex++; + endCol++; + } + } + + // Incremenet the end index so it is at the start of the next character + endIndex++; + + // Calculate the start _column_, converting the the string indexes back to + // column coordinates. + const start = + startIndex // The index of the selection's start char in the line string + + charOffset // The difference between the initial char's column and index + - leftWideCharCount // The number of wide chars left of the initial char + + leftLongCharOffset; // The number of additional chars left of the initial char added by columns with strings longer than 1 (emojis) + + // Calculate the length in _columns_, converting the the string indexes back + // to column coordinates. + const length = Math.min(this._terminal.cols, // Disallow lengths larger than the terminal cols + endIndex // The index of the selection's end char in the line string + - startIndex // The index of the selection's start char in the line string + + leftWideCharCount // The number of wide chars left of the initial char + + rightWideCharCount // The number of wide chars right of the initial char (inclusive) + - leftLongCharOffset // The number of additional chars left of the initial char added by columns with strings longer than 1 (emojis) + - rightLongCharOffset); // The number of additional chars right of the initial char (inclusive) added by columns with strings longer than 1 (emojis) + + return { start, length }; + } + + /** + * Selects the word at the coordinates specified. + * @param coords The coordinates to get the word at. + */ + protected _selectWordAt(coords: [number, number]): void { + const wordPosition = this._getWordAt(coords); + if (wordPosition) { + this._model.selectionStart = [wordPosition.start, coords[1]]; + this._model.selectionStartLength = wordPosition.length; + } + } + + /** + * Sets the selection end to the word at the coordinated specified. + * @param coords The coordinates to get the word at. + */ + private _selectToWordAt(coords: [number, number]): void { + const wordPosition = this._getWordAt(coords); + if (wordPosition) { + this._model.selectionEnd = [this._model.areSelectionValuesReversed() ? wordPosition.start : (wordPosition.start + wordPosition.length), coords[1]]; + } + } + + /** + * Gets whether the character is considered a word separator by the select + * word logic. + * @param char The character to check. + */ + private _isCharWordSeparator(charData: CharData): boolean { + // Zero width characters are never separators as they are always to the + // right of wide characters + if (charData[CHAR_DATA_WIDTH_INDEX] === 0) { + return false; + } + return WORD_SEPARATORS.indexOf(charData[CHAR_DATA_CHAR_INDEX]) >= 0; + } + + /** + * Selects the line specified. + * @param line The line index. + */ + protected _selectLineAt(line: number): void { + this._model.selectionStart = [0, line]; + this._model.selectionStartLength = this._terminal.cols; + } +} diff --git a/xterm.js/src/SelectionModel.test.ts b/xterm.js/src/SelectionModel.test.ts new file mode 100644 index 0000000..e195d6b --- /dev/null +++ b/xterm.js/src/SelectionModel.test.ts @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert } from 'chai'; +import { ITerminal } from './Interfaces'; +import { SelectionModel } from './SelectionModel'; +import {BufferSet} from './BufferSet'; +import { MockTerminal } from './utils/TestUtils.test'; + +class TestSelectionModel extends SelectionModel { + constructor( + terminal: ITerminal + ) { + super(terminal); + } +} + +describe('SelectionManager', () => { + let window: Window; + let document: Document; + + let terminal: ITerminal; + let model: TestSelectionModel; + + beforeEach(() => { + terminal = new MockTerminal(); + terminal.cols = 80; + terminal.rows = 2; + terminal.options.scrollback = 10; + terminal.buffers = new BufferSet(terminal); + terminal.buffer = terminal.buffers.active; + + model = new TestSelectionModel(terminal); + }); + + describe('clearSelection', () => { + it('should clear the final selection', () => { + model.selectionStart = [0, 0]; + model.selectionEnd = [10, 2]; + assert.deepEqual(model.finalSelectionStart, [0, 0]); + assert.deepEqual(model.finalSelectionEnd, [10, 2]); + model.clearSelection(); + assert.deepEqual(model.finalSelectionStart, null); + assert.deepEqual(model.finalSelectionEnd, null); + }); + }); + + describe('areSelectionValuesReversed', () => { + it('should return true when the selection end is before selection start', () => { + model.selectionStart = [1, 0]; + model.selectionEnd = [0, 0]; + assert.equal(model.areSelectionValuesReversed(), true); + model.selectionStart = [10, 2]; + model.selectionEnd = [0, 0]; + assert.equal(model.areSelectionValuesReversed(), true); + }); + it('should return false when the selection end is after selection start', () => { + model.selectionStart = [0, 0]; + model.selectionEnd = [1, 0]; + assert.equal(model.areSelectionValuesReversed(), false); + model.selectionStart = [0, 0]; + model.selectionEnd = [10, 2]; + assert.equal(model.areSelectionValuesReversed(), false); + }); + }); + + describe('onTrim', () => { + it('should trim a portion of the selection when a part of it is trimmed', () => { + model.selectionStart = [0, 0]; + model.selectionEnd = [10, 2]; + model.onTrim(1); + assert.deepEqual(model.finalSelectionStart, [0, 0]); + assert.deepEqual(model.finalSelectionEnd, [10, 1]); + model.onTrim(1); + assert.deepEqual(model.finalSelectionStart, [0, 0]); + assert.deepEqual(model.finalSelectionEnd, [10, 0]); + }); + it('should clear selection when it is trimmed in its entirety', () => { + model.selectionStart = [0, 0]; + model.selectionEnd = [10, 0]; + model.onTrim(1); + assert.deepEqual(model.finalSelectionStart, null); + assert.deepEqual(model.finalSelectionEnd, null); + }); + }); + + describe('finalSelectionStart', () => { + it('should return the start of the buffer if select all is active', () => { + model.isSelectAllActive = true; + assert.deepEqual(model.finalSelectionStart, [0, 0]); + }); + it('should return selection start if there is no selection end', () => { + model.selectionStart = [2, 2]; + assert.deepEqual(model.finalSelectionStart, [2, 2]); + }); + it('should return selection end if values are reversed', () => { + model.selectionStart = [2, 2]; + model.selectionEnd = [3, 2]; + assert.deepEqual(model.finalSelectionStart, [2, 2]); + model.selectionEnd = [1, 2]; + assert.deepEqual(model.finalSelectionStart, [1, 2]); + }); + }); + + describe('finalSelectionEnd', () => { + it('should return the end of the buffer if select all is active', () => { + model.isSelectAllActive = true; + assert.deepEqual(model.finalSelectionEnd, [80, 1]); + }); + it('should return null if there is no selection start', () => { + assert.equal(model.finalSelectionEnd, null); + model.selectionEnd = [1, 2]; + assert.equal(model.finalSelectionEnd, null); + }); + it('should return selection start + length if there is no selection end', () => { + model.selectionStart = [2, 2]; + model.selectionStartLength = 2; + assert.deepEqual(model.finalSelectionEnd, [4, 2]); + }); + it('should return selection start + length if values are reversed', () => { + model.selectionStart = [2, 2]; + model.selectionStartLength = 2; + model.selectionEnd = [2, 1]; + assert.deepEqual(model.finalSelectionEnd, [4, 2]); + }); + it('should return selection start + length if selection end is inside the start selection', () => { + model.selectionStart = [2, 2]; + model.selectionStartLength = 2; + model.selectionEnd = [3, 2]; + assert.deepEqual(model.finalSelectionEnd, [4, 2]); + }); + it('should return selection end if selection end is after selection start + length', () => { + model.selectionStart = [2, 2]; + model.selectionStartLength = 2; + model.selectionEnd = [5, 2]; + assert.deepEqual(model.finalSelectionEnd, [5, 2]); + }); + }); +}); diff --git a/xterm.js/src/SelectionModel.ts b/xterm.js/src/SelectionModel.ts new file mode 100644 index 0000000..5982b1e --- /dev/null +++ b/xterm.js/src/SelectionModel.ts @@ -0,0 +1,132 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ITerminal } from './Interfaces'; + +/** + * Represents a selection within the buffer. This model only cares about column + * and row coordinates, not wide characters. + */ +export class SelectionModel { + /** + * Whether select all is currently active. + */ + public isSelectAllActive: boolean; + + /** + * The [x, y] position the selection starts at. + */ + public selectionStart: [number, number]; + + /** + * The minimal length of the selection from the start position. When double + * clicking on a word, the word will be selected which makes the selection + * start at the start of the word and makes this variable the length. + */ + public selectionStartLength: number; + + /** + * The [x, y] position the selection ends at. + */ + public selectionEnd: [number, number]; + + constructor( + private _terminal: ITerminal + ) { + this.clearSelection(); + } + + /** + * Clears the current selection. + */ + public clearSelection(): void { + this.selectionStart = null; + this.selectionEnd = null; + this.isSelectAllActive = false; + this.selectionStartLength = 0; + } + + /** + * The final selection start, taking into consideration select all. + */ + public get finalSelectionStart(): [number, number] { + if (this.isSelectAllActive) { + return [0, 0]; + } + + if (!this.selectionEnd || !this.selectionStart) { + return this.selectionStart; + } + + return this.areSelectionValuesReversed() ? this.selectionEnd : this.selectionStart; + } + + /** + * The final selection end, taking into consideration select all, double click + * word selection and triple click line selection. + */ + public get finalSelectionEnd(): [number, number] { + if (this.isSelectAllActive) { + return [this._terminal.cols, this._terminal.buffer.ybase + this._terminal.rows - 1]; + } + + if (!this.selectionStart) { + return null; + } + + // Use the selection start if the end doesn't exist or they're reversed + if (!this.selectionEnd || this.areSelectionValuesReversed()) { + return [this.selectionStart[0] + this.selectionStartLength, this.selectionStart[1]]; + } + + // Ensure the the word/line is selected after a double/triple click + if (this.selectionStartLength) { + // Select the larger of the two when start and end are on the same line + if (this.selectionEnd[1] === this.selectionStart[1]) { + return [Math.max(this.selectionStart[0] + this.selectionStartLength, this.selectionEnd[0]), this.selectionEnd[1]]; + } + } + return this.selectionEnd; + } + + /** + * Returns whether the selection start and end are reversed. + */ + public areSelectionValuesReversed(): boolean { + const start = this.selectionStart; + const end = this.selectionEnd; + if (!start || !end) { + return false; + } + return start[1] > end[1] || (start[1] === end[1] && start[0] > end[0]); + } + + /** + * Handle the buffer being trimmed, adjust the selection position. + * @param amount The amount the buffer is being trimmed. + * @return Whether a refresh is necessary. + */ + public onTrim(amount: number): boolean { + // Adjust the selection position based on the trimmed amount. + if (this.selectionStart) { + this.selectionStart[1] -= amount; + } + if (this.selectionEnd) { + this.selectionEnd[1] -= amount; + } + + // The selection has moved off the buffer, clear it. + if (this.selectionEnd && this.selectionEnd[1] < 0) { + this.clearSelection(); + return true; + } + + // If the selection start is trimmed, ensure the start column is 0. + if (this.selectionStart && this.selectionStart[1] < 0) { + this.selectionStart[1] = 0; + } + return false; + } +} diff --git a/xterm.js/src/Terminal.integration.ts b/xterm.js/src/Terminal.integration.ts new file mode 100644 index 0000000..00db4dd --- /dev/null +++ b/xterm.js/src/Terminal.integration.ts @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + * + * This file contains integration tests for xterm.js. + */ + +import * as cp from 'child_process'; +import * as glob from 'glob'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import * as pty from 'node-pty'; +import { assert } from 'chai'; +import { Terminal } from './Terminal'; +import { CHAR_DATA_CHAR_INDEX } from './Buffer'; + +let primitive_pty: any; + +// fake sychronous pty write - read +// we just pipe the data from slave to master as a child program would do +// pty.js opens pipe fds with O_NONBLOCK +// just wait 10ms instead of setting fds to blocking mode +function ptyWriteRead(data: string, cb: (result: string) => void): void { + fs.writeSync(primitive_pty.slave, data); + setTimeout(() => { + let b = new Buffer(64000); + let bytes = fs.readSync(primitive_pty.master, b, 0, 64000, null); + cb(b.toString('utf8', 0, bytes)); + }); +} + +// make sure raw pty is at x=0 and has no pending data +function ptyReset(cb: (result: string) => void): void { + ptyWriteRead('\r\n', cb); +} + +/* debug helpers */ +// generate colorful noisy output to compare xterm and emulator cell states +function formatError(in_: string, out_: string, expected: string): string { + function addLineNumber(start: number, color: string): (s: string) => string { + let counter = start || 0; + return function(s: string): string { + counter += 1; + return '\x1b[33m' + (' ' + counter).slice(-2) + color + s; + }; + } + let line80 = '12345678901234567890123456789012345678901234567890123456789012345678901234567890'; + let s = ''; + s += '\n\x1b[34m' + JSON.stringify(in_); + s += '\n\x1b[33m ' + line80 + '\n'; + s += out_.split('\n').map(addLineNumber(0, '\x1b[31m')).join('\n'); + s += '\n\x1b[33m ' + line80 + '\n'; + s += expected.split('\n').map(addLineNumber(0, '\x1b[32m')).join('\n'); + return s; +} + +// simple debug output of terminal cells +function terminalToString(term: Terminal): string { + let result = ''; + let line_s = ''; + for (let line = term.buffer.ybase; line < term.buffer.ybase + term.rows; line++) { + line_s = ''; + for (let cell = 0; cell < term.cols; ++cell) { + line_s += term.buffer.lines.get(line)[cell][CHAR_DATA_CHAR_INDEX]; + } + // rtrim empty cells as xterm does + line_s = line_s.replace(/\s+$/, ''); + result += line_s; + result += '\n'; + } + return result; +} + +// Skip tests on Windows since pty.open isn't supported +if (os.platform() !== 'win32') { + let CONSOLE_LOG = console.log; + + // expect files need terminal at 80x25! + let COLS = 80; + let ROWS = 25; + + /** some helpers for pty interaction */ + // we need a pty in between to get the termios decorations + // for the basic test cases a raw pty device is enough + primitive_pty = pty.native.open(COLS, ROWS); + + /** tests */ + describe('xterm output comparison', () => { + let xterm; + + beforeEach(() => { + xterm = new Terminal({ cols: COLS, rows: ROWS }); + xterm.refresh = () => {}; + xterm.viewport = { + syncScrollArea: () => {} + }; + }); + + // omit stack trace for escape sequence files + Error.stackTraceLimit = 0; + let files = glob.sync('**/escape_sequence_files/*.in', { cwd: path.join(__dirname, '..')}); + // only successful tests for now + let skip = [ + 10, 16, 17, 19, 32, 33, 34, 35, 36, 39, + 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, + 63, 68 + ]; + if (os.platform() === 'darwin') { + // These are failing on macOS only + skip.push(3, 7, 11, 67); + } + for (let i = 0; i < files.length; i++) { + if (skip.indexOf(i) >= 0) { + continue; + } + ((filename: string) => { + it(filename.split('/').slice(-1)[0], done => { + ptyReset(() => { + let in_file = fs.readFileSync(filename, 'utf8'); + ptyWriteRead(in_file, from_pty => { + // uncomment this to get log from terminal + // console.log = function(){}; + + // Perform a synchronous .write(data) + xterm.writeBuffer.push(from_pty); + xterm.innerWrite(); + + let from_emulator = terminalToString(xterm); + console.log = CONSOLE_LOG; + let expected = fs.readFileSync(filename.split('.')[0] + '.text', 'utf8'); + // Some of the tests have whitespace on the right of lines, we trim all the linex + // from xterm.js so ignore this for now at least. + let expectedRightTrimmed = expected.split('\n').map(l => l.replace(/\s+$/, '')).join('\n'); + if (from_emulator !== expectedRightTrimmed) { + // uncomment to get noisy output + throw new Error(formatError(in_file, from_emulator, expected)); + // throw new Error('mismatch'); + } + done(); + }); + }); + }); + })(files[i]); + } + }); +} + +describe('typings', () => { + it('should throw no compile errors', function (): void { + this.timeout(20000); + let tsc = path.join(__dirname, '..', 'node_modules', '.bin', 'tsc'); + if (process.platform === 'win32') { + tsc += '.cmd'; + } + const fixtureDir = path.join(__dirname, '..', 'fixtures', 'typings-test'); + let result = cp.spawnSync(tsc, { cwd: fixtureDir }); + assert.equal(result.status, 0, `build did not succeed:\nstdout: ${result.stdout.toString()}\nstderr: ${result.stderr.toString()}\n`); + // Clean up + fs.unlinkSync(path.join(fixtureDir, 'typings-test.js')); + }); +}); diff --git a/xterm.js/src/Terminal.test.ts b/xterm.js/src/Terminal.test.ts new file mode 100644 index 0000000..9cb0b75 --- /dev/null +++ b/xterm.js/src/Terminal.test.ts @@ -0,0 +1,1037 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert, expect } from 'chai'; +import { Terminal } from './Terminal'; +import * as attach from './addons/attach/attach'; +import { MockViewport, MockCompositionHelper, MockRenderer } from './utils/TestUtils.test'; +import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from './Buffer'; + +const INIT_COLS = 80; +const INIT_ROWS = 24; + +class TestTerminal extends Terminal { + public evaluateKeyEscapeSequence(ev: any): {cancel: boolean, key: string, scrollLines: number} { return this._evaluateKeyEscapeSequence(ev); } + public keyDown(ev: any): boolean { return this._keyDown(ev); } + public keyPress(ev: any): boolean { return this._keyPress(ev); } +} + +describe('term.js addons', () => { + let term: TestTerminal; + + beforeEach(() => { + term = new TestTerminal({ + cols: INIT_COLS, + rows: INIT_ROWS + }); + term.refresh = () => {}; + (term).renderer = new MockRenderer(); + term.viewport = new MockViewport(); + (term).compositionHelper = new MockCompositionHelper(); + // Force synchronous writes + term.write = (data) => { + term.writeBuffer.push(data); + (term).innerWrite(); + }; + (term).element = { + classList: { + toggle: () => {}, + remove: () => {} + } + }; + }); + + it('should apply addons with Terminal.applyAddon', () => { + Terminal.applyAddon(attach); + // Test that addon was applied successfully, adding attach to Terminal's + // prototype. + assert.equal(typeof (Terminal).prototype.attach, 'function'); + }); + + describe('getOption', () => { + it('should retrieve the option correctly', () => { + // In the `options` namespace. + term.options.cursorBlink = true; + assert.equal(term.getOption('cursorBlink'), true); + + // On the Terminal instance + delete term.options.cursorBlink; + term.options.cursorBlink = false; + assert.equal(term.getOption('cursorBlink'), false); + }); + it('should throw when retrieving a non-existant option', () => { + assert.throws(term.getOption.bind(term, 'fake', true)); + }); + }); + + describe('attachCustomKeyEventHandler', () => { + let evKeyDown = { + preventDefault: () => {}, + stopPropagation: () => {}, + type: 'keydown', + keyCode: 77 + }; + let evKeyPress = { + preventDefault: () => {}, + stopPropagation: () => {}, + type: 'keypress', + keyCode: 77 + }; + + beforeEach(() => { + term.handler = () => {}; + term.showCursor = () => {}; + term.clearSelection = () => {}; + }); + + it('should process the keydown/keypress event based on what the handler returns', () => { + assert.equal(term.keyDown(evKeyDown), true); + assert.equal(term.keyPress(evKeyPress), true); + term.attachCustomKeyEventHandler(ev => ev.keyCode === 77); + assert.equal(term.keyDown(evKeyDown), true); + assert.equal(term.keyPress(evKeyPress), true); + term.attachCustomKeyEventHandler(ev => ev.keyCode !== 77); + assert.equal(term.keyDown(evKeyDown), false); + assert.equal(term.keyPress(evKeyPress), false); + }); + + it('should alive after reset(ESC c Full Reset (RIS))', () => { + term.attachCustomKeyEventHandler(ev => ev.keyCode !== 77); + assert.equal(term.keyDown(evKeyDown), false); + assert.equal(term.keyPress(evKeyPress), false); + term.reset(); + assert.equal(term.keyDown(evKeyDown), false); + assert.equal(term.keyPress(evKeyPress), false); + }); + }); + + describe('setOption', () => { + it('should set the option correctly', () => { + term.setOption('cursorBlink', true); + assert.equal(term.options.cursorBlink, true); + term.setOption('cursorBlink', false); + assert.equal(term.options.cursorBlink, false); + }); + it('should throw when setting a non-existant option', () => { + assert.throws(term.setOption.bind(term, 'fake', true)); + }); + }); + + describe('clear', () => { + it('should clear a buffer equal to rows', () => { + let promptLine = term.buffer.lines.get(term.buffer.ybase + term.buffer.y); + term.clear(); + assert.equal(term.buffer.y, 0); + assert.equal(term.buffer.ybase, 0); + assert.equal(term.buffer.ydisp, 0); + assert.equal(term.buffer.lines.length, term.rows); + assert.deepEqual(term.buffer.lines.get(0), promptLine); + for (let i = 1; i < term.rows; i++) { + assert.deepEqual(term.buffer.lines.get(i), term.blankLine()); + } + }); + it('should clear a buffer larger than rows', () => { + // Fill the buffer with dummy rows + for (let i = 0; i < term.rows * 2; i++) { + term.write('test\n'); + } + + let promptLine = term.buffer.lines.get(term.buffer.ybase + term.buffer.y); + term.clear(); + assert.equal(term.buffer.y, 0); + assert.equal(term.buffer.ybase, 0); + assert.equal(term.buffer.ydisp, 0); + assert.equal(term.buffer.lines.length, term.rows); + assert.deepEqual(term.buffer.lines.get(0), promptLine); + for (let i = 1; i < term.rows; i++) { + assert.deepEqual(term.buffer.lines.get(i), term.blankLine()); + } + }); + it('should not break the prompt when cleared twice', () => { + let promptLine = term.buffer.lines.get(term.buffer.ybase + term.buffer.y); + term.clear(); + term.clear(); + assert.equal(term.buffer.y, 0); + assert.equal(term.buffer.ybase, 0); + assert.equal(term.buffer.ydisp, 0); + assert.equal(term.buffer.lines.length, term.rows); + assert.deepEqual(term.buffer.lines.get(0), promptLine); + for (let i = 1; i < term.rows; i++) { + assert.deepEqual(term.buffer.lines.get(i), term.blankLine()); + } + }); + }); + + describe('scroll', () => { + describe('scrollLines', () => { + let startYDisp; + beforeEach(() => { + for (let i = 0; i < term.rows * 2; i++) { + term.writeln('test'); + } + startYDisp = term.rows + 1; + }); + it('should scroll a single line', () => { + assert.equal(term.buffer.ydisp, startYDisp); + term.scrollLines(-1); + assert.equal(term.buffer.ydisp, startYDisp - 1); + term.scrollLines(1); + assert.equal(term.buffer.ydisp, startYDisp); + }); + it('should scroll multiple lines', () => { + assert.equal(term.buffer.ydisp, startYDisp); + term.scrollLines(-5); + assert.equal(term.buffer.ydisp, startYDisp - 5); + term.scrollLines(5); + assert.equal(term.buffer.ydisp, startYDisp); + }); + it('should not scroll beyond the bounds of the buffer', () => { + assert.equal(term.buffer.ydisp, startYDisp); + term.scrollLines(1); + assert.equal(term.buffer.ydisp, startYDisp); + for (let i = 0; i < startYDisp; i++) { + term.scrollLines(-1); + } + assert.equal(term.buffer.ydisp, 0); + term.scrollLines(-1); + assert.equal(term.buffer.ydisp, 0); + }); + }); + + describe('scrollPages', () => { + let startYDisp; + beforeEach(() => { + for (let i = 0; i < term.rows * 3; i++) { + term.writeln('test'); + } + startYDisp = (term.rows * 2) + 1; + }); + it('should scroll a single page', () => { + assert.equal(term.buffer.ydisp, startYDisp); + term.scrollPages(-1); + assert.equal(term.buffer.ydisp, startYDisp - (term.rows - 1)); + term.scrollPages(1); + assert.equal(term.buffer.ydisp, startYDisp); + }); + it('should scroll a multiple pages', () => { + assert.equal(term.buffer.ydisp, startYDisp); + term.scrollPages(-2); + assert.equal(term.buffer.ydisp, startYDisp - (term.rows - 1) * 2); + term.scrollPages(2); + assert.equal(term.buffer.ydisp, startYDisp); + }); + }); + + describe('scrollToTop', () => { + beforeEach(() => { + for (let i = 0; i < term.rows * 3; i++) { + term.writeln('test'); + } + }); + it('should scroll to the top', () => { + assert.notEqual(term.buffer.ydisp, 0); + term.scrollToTop(); + assert.equal(term.buffer.ydisp, 0); + }); + }); + + describe('scrollToBottom', () => { + let startYDisp; + beforeEach(() => { + for (let i = 0; i < term.rows * 3; i++) { + term.writeln('test'); + } + startYDisp = (term.rows * 2) + 1; + }); + it('should scroll to the bottom', () => { + term.scrollLines(-1); + term.scrollToBottom(); + assert.equal(term.buffer.ydisp, startYDisp); + term.scrollPages(-1); + term.scrollToBottom(); + assert.equal(term.buffer.ydisp, startYDisp); + term.scrollToTop(); + term.scrollToBottom(); + assert.equal(term.buffer.ydisp, startYDisp); + }); + }); + + describe('keyDown', () => { + it('should scroll down, when a key is pressed and terminal is scrolled up', () => { + // Override _evaluateKeyEscapeSequence to return cancel code + (term)._evaluateKeyEscapeSequence = () => { + return { key: 'a' }; + }; + let event = { + type: 'keydown', + keyCode: 0, + preventDefault: () => {}, + stopPropagation: () => {} + }; + + term.buffer.ydisp = 0; + term.buffer.ybase = 40; + term.keyDown(event); + + // Ensure that now the terminal is scrolled to bottom + assert.equal(term.buffer.ydisp, term.buffer.ybase); + }); + + it('should not scroll down, when a custom keydown handler prevents the event', () => { + // Add some output to the terminal + for (let i = 0; i < term.rows * 3; i++) { + term.writeln('test'); + } + let startYDisp = (term.rows * 2) + 1; + term.attachCustomKeyEventHandler(() => { + return false; + }); + + assert.equal(term.buffer.ydisp, startYDisp); + term.scrollLines(-1); + assert.equal(term.buffer.ydisp, startYDisp - 1); + term.keyDown({ keyCode: 0 }); + assert.equal(term.buffer.ydisp, startYDisp - 1); + }); + }); + + describe('scroll() function', () => { + describe('when scrollback > 0', () => { + it('should create a new line and scroll', () => { + term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a'; + term.buffer.lines.get(INIT_ROWS - 1)[0][CHAR_DATA_CHAR_INDEX] = 'b'; + term.buffer.y = INIT_ROWS - 1; // Move cursor to last line + term.scroll(); + assert.equal(term.buffer.lines.length, INIT_ROWS + 1); + assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'a'); + assert.equal(term.buffer.lines.get(INIT_ROWS - 1)[0][CHAR_DATA_CHAR_INDEX], 'b'); + assert.equal(term.buffer.lines.get(INIT_ROWS)[0][CHAR_DATA_CHAR_INDEX], ' '); + }); + + it('should properly scroll inside a scroll region (scrollTop set)', () => { + term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a'; + term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b'; + term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX] = 'c'; + term.buffer.y = INIT_ROWS - 1; // Move cursor to last line + term.buffer.scrollTop = 1; + term.scroll(); + assert.equal(term.buffer.lines.length, INIT_ROWS); + assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'a'); + assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], 'c'); + }); + + it('should properly scroll inside a scroll region (scrollBottom set)', () => { + term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a'; + term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b'; + term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX] = 'c'; + term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX] = 'd'; + term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX] = 'e'; + term.buffer.y = 3; + term.buffer.scrollBottom = 3; + term.scroll(); + assert.equal(term.buffer.lines.length, INIT_ROWS + 1); + assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'a', '\'a\' should be pushed to the scrollback'); + assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], 'b'); + assert.equal(term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX], 'c'); + assert.equal(term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX], 'd'); + assert.equal(term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX], ' ', 'a blank line should be added at scrollBottom\'s index'); + assert.equal(term.buffer.lines.get(5)[0][CHAR_DATA_CHAR_INDEX], 'e'); + }); + + it('should properly scroll inside a scroll region (scrollTop and scrollBottom set)', () => { + term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a'; + term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b'; + term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX] = 'c'; + term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX] = 'd'; + term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX] = 'e'; + term.buffer.y = INIT_ROWS - 1; // Move cursor to last line + term.buffer.scrollTop = 1; + term.buffer.scrollBottom = 3; + term.scroll(); + assert.equal(term.buffer.lines.length, INIT_ROWS); + assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'a'); + assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], 'c', '\'b\' should be removed from the buffer'); + assert.equal(term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX], 'd'); + assert.equal(term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX], ' ', 'a blank line should be added at scrollBottom\'s index'); + assert.equal(term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX], 'e'); + }); + }); + + describe('when scrollback === 0', () => { + beforeEach(() => { + term.setOption('scrollback', 0); + assert.equal(term.buffer.lines.maxLength, INIT_ROWS); + }); + + it('should create a new line and shift everything up', () => { + term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a'; + term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b'; + term.buffer.lines.get(INIT_ROWS - 1)[0][CHAR_DATA_CHAR_INDEX] = 'c'; + term.buffer.y = INIT_ROWS - 1; // Move cursor to last line + assert.equal(term.buffer.lines.length, INIT_ROWS); + term.scroll(); + assert.equal(term.buffer.lines.length, INIT_ROWS); + // 'a' gets pushed out of buffer + assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'b'); + assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], ' '); + assert.equal(term.buffer.lines.get(INIT_ROWS - 2)[0][CHAR_DATA_CHAR_INDEX], 'c'); + assert.equal(term.buffer.lines.get(INIT_ROWS - 1)[0][CHAR_DATA_CHAR_INDEX], ' '); + }); + + it('should properly scroll inside a scroll region (scrollTop set)', () => { + term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a'; + term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b'; + term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX] = 'c'; + term.buffer.y = INIT_ROWS - 1; // Move cursor to last line + term.buffer.scrollTop = 1; + term.scroll(); + assert.equal(term.buffer.lines.length, INIT_ROWS); + assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'a'); + assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], 'c'); + }); + + it('should properly scroll inside a scroll region (scrollBottom set)', () => { + term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a'; + term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b'; + term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX] = 'c'; + term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX] = 'd'; + term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX] = 'e'; + term.buffer.y = 3; + term.buffer.scrollBottom = 3; + term.scroll(); + assert.equal(term.buffer.lines.length, INIT_ROWS); + assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'b'); + assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], 'c'); + assert.equal(term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX], 'd'); + assert.equal(term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX], ' ', 'a blank line should be added at scrollBottom\'s index'); + assert.equal(term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX], 'e'); + }); + + it('should properly scroll inside a scroll region (scrollTop and scrollBottom set)', () => { + term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a'; + term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b'; + term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX] = 'c'; + term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX] = 'd'; + term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX] = 'e'; + term.buffer.y = INIT_ROWS - 1; // Move cursor to last line + term.buffer.scrollTop = 1; + term.buffer.scrollBottom = 3; + term.scroll(); + assert.equal(term.buffer.lines.length, INIT_ROWS); + assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'a'); + assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], 'c', '\'b\' should be removed from the buffer'); + assert.equal(term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX], 'd'); + assert.equal(term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX], ' ', 'a blank line should be added at scrollBottom\'s index'); + assert.equal(term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX], 'e'); + }); + }); + }); + }); + + describe('evaluateKeyEscapeSequence', () => { + it('should return the correct escape sequence for unmodified keys', () => { + // Backspace + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 8 }).key, '\x7f'); // ^? + // Tab + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 9 }).key, '\t'); + // Return/enter + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 13 }).key, '\r'); // CR + // Escape + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 27 }).key, '\x1b'); + // Page up, page down + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 33 }).key, '\x1b[5~'); // CSI 5 ~ + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 34 }).key, '\x1b[6~'); // CSI 6 ~ + // End, Home + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 35 }).key, '\x1b[F'); // SS3 F + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 36 }).key, '\x1b[H'); // SS3 H + // Left, up, right, down arrows + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 37 }).key, '\x1b[D'); // CSI D + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 38 }).key, '\x1b[A'); // CSI A + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 39 }).key, '\x1b[C'); // CSI C + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 40 }).key, '\x1b[B'); // CSI B + // Insert + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 45 }).key, '\x1b[2~'); // CSI 2 ~ + // Delete + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 46 }).key, '\x1b[3~'); // CSI 3 ~ + // F1-F12 + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 112 }).key, '\x1bOP'); // SS3 P + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 113 }).key, '\x1bOQ'); // SS3 Q + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 114 }).key, '\x1bOR'); // SS3 R + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 115 }).key, '\x1bOS'); // SS3 S + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 116 }).key, '\x1b[15~'); // CSI 1 5 ~ + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 117 }).key, '\x1b[17~'); // CSI 1 7 ~ + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 118 }).key, '\x1b[18~'); // CSI 1 8 ~ + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 119 }).key, '\x1b[19~'); // CSI 1 9 ~ + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 120 }).key, '\x1b[20~'); // CSI 2 0 ~ + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 121 }).key, '\x1b[21~'); // CSI 2 1 ~ + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 122 }).key, '\x1b[23~'); // CSI 2 3 ~ + assert.equal(term.evaluateKeyEscapeSequence({ keyCode: 123 }).key, '\x1b[24~'); // CSI 2 4 ~ + }); + it('should return \\x1b[3;5~ for ctrl+delete', () => { + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 46 }).key, '\x1b[3;5~'); + }); + it('should return \\x1b[3;2~ for shift+delete', () => { + assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 46 }).key, '\x1b[3;2~'); + }); + it('should return \\x1b[3;3~ for alt+delete', () => { + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 46 }).key, '\x1b[3;3~'); + }); + it('should return \\x1b[5D for ctrl+left', () => { + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 37 }).key, '\x1b[1;5D'); // CSI 5 D + }); + it('should return \\x1b[5C for ctrl+right', () => { + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 39 }).key, '\x1b[1;5C'); // CSI 5 C + }); + it('should return \\x1b[5A for ctrl+up', () => { + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 38 }).key, '\x1b[1;5A'); // CSI 5 A + }); + it('should return \\x1b[5B for ctrl+down', () => { + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 40 }).key, '\x1b[1;5B'); // CSI 5 B + }); + + describe('On non-macOS platforms', () => { + beforeEach(() => { + term.browser.isMac = false; + }); + // Evalueate alt + arrow key movement, which is a feature of terminal emulators but not VT100 + // http://unix.stackexchange.com/a/108106 + it('should return \\x1b[5D for alt+left', () => { + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 37 }).key, '\x1b[1;5D'); // CSI 5 D + }); + it('should return \\x1b[5C for alt+right', () => { + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 39 }).key, '\x1b[1;5C'); // CSI 5 C + }); + }); + + describe('On macOS platforms', () => { + beforeEach(() => { + term.browser.isMac = true; + }); + it('should return \\x1bb for alt+left', () => { + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 37 }).key, '\x1bb'); // CSI 5 D + }); + it('should return \\x1bf for alt+right', () => { + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 39 }).key, '\x1bf'); // CSI 5 C + }); + }); + + it('should return \\x1b[5A for alt+up', () => { + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 38 }).key, '\x1b[1;5A'); // CSI 5 A + }); + it('should return \\x1b[5B for alt+down', () => { + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 40 }).key, '\x1b[1;5B'); // CSI 5 B + }); + it('should return the correct escape sequence for modified F1-F12 keys', () => { + assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 112 }).key, '\x1b[1;2P'); + assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 113 }).key, '\x1b[1;2Q'); + assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 114 }).key, '\x1b[1;2R'); + assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 115 }).key, '\x1b[1;2S'); + assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 116 }).key, '\x1b[15;2~'); + assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 117 }).key, '\x1b[17;2~'); + assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 118 }).key, '\x1b[18;2~'); + assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 119 }).key, '\x1b[19;2~'); + assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 120 }).key, '\x1b[20;2~'); + assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 121 }).key, '\x1b[21;2~'); + assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 122 }).key, '\x1b[23;2~'); + assert.equal(term.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 123 }).key, '\x1b[24;2~'); + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 112 }).key, '\x1b[1;3P'); + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 113 }).key, '\x1b[1;3Q'); + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 114 }).key, '\x1b[1;3R'); + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 115 }).key, '\x1b[1;3S'); + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 116 }).key, '\x1b[15;3~'); + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 117 }).key, '\x1b[17;3~'); + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 118 }).key, '\x1b[18;3~'); + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 119 }).key, '\x1b[19;3~'); + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 120 }).key, '\x1b[20;3~'); + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 121 }).key, '\x1b[21;3~'); + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 122 }).key, '\x1b[23;3~'); + assert.equal(term.evaluateKeyEscapeSequence({ altKey: true, keyCode: 123 }).key, '\x1b[24;3~'); + + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 112 }).key, '\x1b[1;5P'); + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 113 }).key, '\x1b[1;5Q'); + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 114 }).key, '\x1b[1;5R'); + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 115 }).key, '\x1b[1;5S'); + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 116 }).key, '\x1b[15;5~'); + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 117 }).key, '\x1b[17;5~'); + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 118 }).key, '\x1b[18;5~'); + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 119 }).key, '\x1b[19;5~'); + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 120 }).key, '\x1b[20;5~'); + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 121 }).key, '\x1b[21;5~'); + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 122 }).key, '\x1b[23;5~'); + assert.equal(term.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 123 }).key, '\x1b[24;5~'); + }); + }); + + describe('Third level shift', () => { + let evKeyDown; + let evKeyPress; + + beforeEach(() => { + term.handler = () => {}; + term.showCursor = () => {}; + term.clearSelection = () => {}; + // term.compositionHelper = { + // isComposing: false, + // keydown: { + // bind: () => { + // return () => { return true; }; + // } + // } + // }; + evKeyDown = { + preventDefault: () => {}, + stopPropagation: () => {}, + type: 'keydown', + altKey: null, + keyCode: null + }; + evKeyPress = { + preventDefault: () => {}, + stopPropagation: () => {}, + type: 'keypress', + altKey: null, + charCode: null, + keyCode: null + }; + }); + + describe('On Mac OS', () => { + beforeEach(() => { + term.browser.isMac = true; + }); + + it('should not interfere with the alt key on keyDown', () => { + evKeyDown.altKey = true; + evKeyDown.keyCode = 81; + assert.equal(term.keyDown(evKeyDown), true); + evKeyDown.altKey = true; + evKeyDown.keyCode = 192; + assert.equal(term.keyDown(evKeyDown), true); + }); + + it('should interefere with the alt + arrow keys', () => { + evKeyDown.altKey = true; + evKeyDown.keyCode = 37; + assert.equal(term.keyDown(evKeyDown), false); + evKeyDown.altKey = true; + evKeyDown.keyCode = 39; + assert.equal(term.keyDown(evKeyDown), false); + }); + + it('should emit key with alt + key on keyPress', (done) => { + let keys = ['@', '@', '\\', '\\', '|', '|']; + + term.on('keypress', (key) => { + if (key) { + let index = keys.indexOf(key); + assert(index !== -1, 'Emitted wrong key: ' + key); + keys.splice(index, 1); + } + if (keys.length === 0) done(); + }); + + evKeyPress.altKey = true; + // @ + evKeyPress.charCode = null; + evKeyPress.keyCode = 64; + term.keyPress(evKeyPress); + // Firefox @ + evKeyPress.charCode = 64; + evKeyPress.keyCode = 0; + term.keyPress(evKeyPress); + // \ + evKeyPress.charCode = null; + evKeyPress.keyCode = 92; + term.keyPress(evKeyPress); + // Firefox \ + evKeyPress.charCode = 92; + evKeyPress.keyCode = 0; + term.keyPress(evKeyPress); + // | + evKeyPress.charCode = null; + evKeyPress.keyCode = 124; + term.keyPress(evKeyPress); + // Firefox | + evKeyPress.charCode = 124; + evKeyPress.keyCode = 0; + term.keyPress(evKeyPress); + }); + }); + + describe('On MS Windows', () => { + beforeEach(() => { + term.browser.isMSWindows = true; + }); + + it('should not interfere with the alt + ctrl key on keyDown', () => { + evKeyPress.altKey = true; + evKeyPress.ctrlKey = true; + evKeyPress.keyCode = 81; + assert.equal(term.keyDown(evKeyPress), true); + evKeyDown.altKey = true; + evKeyDown.ctrlKey = true; + evKeyDown.keyCode = 81; + assert.equal(term.keyDown(evKeyDown), true); + }); + + it('should interefere with the alt + ctrl + arrow keys', () => { + evKeyDown.altKey = true; + evKeyDown.ctrlKey = true; + + evKeyDown.keyCode = 37; + assert.equal(term.keyDown(evKeyDown), false); + evKeyDown.keyCode = 39; + assert.equal(term.keyDown(evKeyDown), false); + }); + + it('should emit key with alt + ctrl + key on keyPress', (done) => { + let keys = ['@', '@', '\\', '\\', '|', '|']; + + term.on('keypress', (key) => { + if (key) { + let index = keys.indexOf(key); + assert(index !== -1, 'Emitted wrong key: ' + key); + keys.splice(index, 1); + } + if (keys.length === 0) done(); + }); + + evKeyPress.altKey = true; + evKeyPress.ctrlKey = true; + + // @ + evKeyPress.charCode = null; + evKeyPress.keyCode = 64; + term.keyPress(evKeyPress); + // Firefox @ + evKeyPress.charCode = 64; + evKeyPress.keyCode = 0; + term.keyPress(evKeyPress); + // \ + evKeyPress.charCode = null; + evKeyPress.keyCode = 92; + term.keyPress(evKeyPress); + // Firefox \ + evKeyPress.charCode = 92; + evKeyPress.keyCode = 0; + term.keyPress(evKeyPress); + // | + evKeyPress.charCode = null; + evKeyPress.keyCode = 124; + term.keyPress(evKeyPress); + // Firefox | + evKeyPress.charCode = 124; + evKeyPress.keyCode = 0; + term.keyPress(evKeyPress); + }); + }); + }); + + describe('unicode - surrogates', () => { + it('2 characters per cell', function (): void { + this.timeout(10000); // This is needed because istanbul patches code and slows it down + let high = String.fromCharCode(0xD800); + for (let i = 0xDC00; i <= 0xDCFF; ++i) { + term.write(high + String.fromCharCode(i)); + let tchar = term.buffer.lines.get(0)[0]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(high + String.fromCharCode(i)); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1); + expect(term.buffer.lines.get(0)[1][CHAR_DATA_CHAR_INDEX]).eql(' '); + term.reset(); + } + }); + it('2 characters at last cell', () => { + let high = String.fromCharCode(0xD800); + for (let i = 0xDC00; i <= 0xDCFF; ++i) { + term.buffer.x = term.cols - 1; + term.write(high + String.fromCharCode(i)); + expect(term.buffer.lines.get(0)[term.buffer.x - 1][CHAR_DATA_CHAR_INDEX]).eql(high + String.fromCharCode(i)); + expect(term.buffer.lines.get(0)[term.buffer.x - 1][CHAR_DATA_CHAR_INDEX].length).eql(2); + expect(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX]).eql(' '); + term.reset(); + } + }); + it('2 characters per cell over line end with autowrap', () => { + let high = String.fromCharCode(0xD800); + for (let i = 0xDC00; i <= 0xDCFF; ++i) { + term.buffer.x = term.cols - 1; + term.wraparoundMode = true; + term.write('a' + high + String.fromCharCode(i)); + expect(term.buffer.lines.get(0)[term.cols - 1][CHAR_DATA_CHAR_INDEX]).eql('a'); + expect(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX]).eql(high + String.fromCharCode(i)); + expect(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX].length).eql(2); + expect(term.buffer.lines.get(1)[1][CHAR_DATA_CHAR_INDEX]).eql(' '); + term.reset(); + } + }); + it('2 characters per cell over line end without autowrap', () => { + let high = String.fromCharCode(0xD800); + for (let i = 0xDC00; i <= 0xDCFF; ++i) { + term.buffer.x = term.cols - 1; + term.wraparoundMode = false; + term.write('a' + high + String.fromCharCode(i)); + // auto wraparound mode should cut off the rest of the line + expect(term.buffer.lines.get(0)[term.cols - 1][CHAR_DATA_CHAR_INDEX]).eql('a'); + expect(term.buffer.lines.get(0)[term.cols - 1][CHAR_DATA_CHAR_INDEX].length).eql(1); + expect(term.buffer.lines.get(1)[1][CHAR_DATA_CHAR_INDEX]).eql(' '); + term.reset(); + } + }); + it('splitted surrogates', () => { + let high = String.fromCharCode(0xD800); + for (let i = 0xDC00; i <= 0xDCFF; ++i) { + term.write(high); + term.write(String.fromCharCode(i)); + let tchar = term.buffer.lines.get(0)[0]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(high + String.fromCharCode(i)); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1); + expect(term.buffer.lines.get(0)[1][CHAR_DATA_CHAR_INDEX]).eql(' '); + term.reset(); + } + }); + }); + + describe('unicode - combining characters', () => { + it('café', () => { + term.write('cafe\u0301'); + expect(term.buffer.lines.get(0)[3][CHAR_DATA_CHAR_INDEX]).eql('e\u0301'); + expect(term.buffer.lines.get(0)[3][CHAR_DATA_CHAR_INDEX].length).eql(2); + expect(term.buffer.lines.get(0)[3][CHAR_DATA_WIDTH_INDEX]).eql(1); + }); + it('café - end of line', () => { + term.buffer.x = term.cols - 1 - 3; + term.write('cafe\u0301'); + expect(term.buffer.lines.get(0)[term.cols - 1][CHAR_DATA_CHAR_INDEX]).eql('e\u0301'); + expect(term.buffer.lines.get(0)[term.cols - 1][CHAR_DATA_CHAR_INDEX].length).eql(2); + expect(term.buffer.lines.get(0)[term.cols - 1][CHAR_DATA_WIDTH_INDEX]).eql(1); + expect(term.buffer.lines.get(0)[1][CHAR_DATA_CHAR_INDEX]).eql(' '); + expect(term.buffer.lines.get(0)[1][CHAR_DATA_CHAR_INDEX].length).eql(1); + expect(term.buffer.lines.get(0)[1][CHAR_DATA_WIDTH_INDEX]).eql(1); + }); + it('multiple combined é', () => { + term.wraparoundMode = true; + term.write(Array(100).join('e\u0301')); + for (let i = 0; i < term.cols; ++i) { + let tchar = term.buffer.lines.get(0)[i]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('e\u0301'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1); + } + let tchar = term.buffer.lines.get(1)[0]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('e\u0301'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1); + }); + it('multiple surrogate with combined', () => { + term.wraparoundMode = true; + term.write(Array(100).join('\uD800\uDC00\u0301')); + for (let i = 0; i < term.cols; ++i) { + let tchar = term.buffer.lines.get(0)[i]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('\uD800\uDC00\u0301'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(3); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1); + } + let tchar = term.buffer.lines.get(1)[0]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('\uD800\uDC00\u0301'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(3); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1); + }); + }); + + describe('unicode - fullwidth characters', () => { + it('cursor movement even', () => { + expect(term.buffer.x).eql(0); + term.write('¥'); + expect(term.buffer.x).eql(2); + }); + it('cursor movement odd', () => { + term.buffer.x = 1; + expect(term.buffer.x).eql(1); + term.write('¥'); + expect(term.buffer.x).eql(3); + }); + it('line of ¥ even', () => { + term.wraparoundMode = true; + term.write(Array(50).join('¥')); + for (let i = 0; i < term.cols; ++i) { + let tchar = term.buffer.lines.get(0)[i]; + if (i % 2) { + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(''); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(0); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(0); + } else { + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2); + } + } + let tchar = term.buffer.lines.get(1)[0]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2); + }); + it('line of ¥ odd', () => { + term.wraparoundMode = true; + term.buffer.x = 1; + term.write(Array(50).join('¥')); + for (let i = 1; i < term.cols - 1; ++i) { + let tchar = term.buffer.lines.get(0)[i]; + if (!(i % 2)) { + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(''); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(0); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(0); + } else { + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2); + } + } + let tchar = term.buffer.lines.get(0)[term.cols - 1]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(' '); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1); + tchar = term.buffer.lines.get(1)[0]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2); + }); + it('line of ¥ with combining odd', () => { + term.wraparoundMode = true; + term.buffer.x = 1; + term.write(Array(50).join('¥\u0301')); + for (let i = 1; i < term.cols - 1; ++i) { + let tchar = term.buffer.lines.get(0)[i]; + if (!(i % 2)) { + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(''); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(0); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(0); + } else { + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥\u0301'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2); + } + } + let tchar = term.buffer.lines.get(0)[term.cols - 1]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(' '); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1); + tchar = term.buffer.lines.get(1)[0]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥\u0301'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2); + }); + it('line of ¥ with combining even', () => { + term.wraparoundMode = true; + term.write(Array(50).join('¥\u0301')); + for (let i = 0; i < term.cols; ++i) { + let tchar = term.buffer.lines.get(0)[i]; + if (i % 2) { + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(''); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(0); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(0); + } else { + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥\u0301'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2); + } + } + let tchar = term.buffer.lines.get(1)[0]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥\u0301'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2); + }); + it('line of surrogate fullwidth with combining odd', () => { + term.wraparoundMode = true; + term.buffer.x = 1; + term.write(Array(50).join('\ud843\ude6d\u0301')); + for (let i = 1; i < term.cols - 1; ++i) { + let tchar = term.buffer.lines.get(0)[i]; + if (!(i % 2)) { + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(''); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(0); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(0); + } else { + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('\ud843\ude6d\u0301'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(3); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2); + } + } + let tchar = term.buffer.lines.get(0)[term.cols - 1]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(' '); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1); + tchar = term.buffer.lines.get(1)[0]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('\ud843\ude6d\u0301'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(3); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2); + }); + it('line of surrogate fullwidth with combining even', () => { + term.wraparoundMode = true; + term.write(Array(50).join('\ud843\ude6d\u0301')); + for (let i = 0; i < term.cols; ++i) { + let tchar = term.buffer.lines.get(0)[i]; + if (i % 2) { + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(''); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(0); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(0); + } else { + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('\ud843\ude6d\u0301'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(3); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2); + } + } + let tchar = term.buffer.lines.get(1)[0]; + expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('\ud843\ude6d\u0301'); + expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(3); + expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2); + }); + }); + + describe('insert mode', () => { + it('halfwidth - all', () => { + term.write(Array(9).join('0123456789').slice(-80)); + term.buffer.x = 10; + term.buffer.y = 0; + term.insertMode = true; + term.write('abcde'); + expect(term.buffer.lines.get(0).length).eql(term.cols); + expect(term.buffer.lines.get(0)[10][CHAR_DATA_CHAR_INDEX]).eql('a'); + expect(term.buffer.lines.get(0)[14][CHAR_DATA_CHAR_INDEX]).eql('e'); + expect(term.buffer.lines.get(0)[15][CHAR_DATA_CHAR_INDEX]).eql('0'); + expect(term.buffer.lines.get(0)[79][CHAR_DATA_CHAR_INDEX]).eql('4'); + }); + it('fullwidth - insert', () => { + term.write(Array(9).join('0123456789').slice(-80)); + term.buffer.x = 10; + term.buffer.y = 0; + term.insertMode = true; + term.write('¥¥¥'); + expect(term.buffer.lines.get(0).length).eql(term.cols); + expect(term.buffer.lines.get(0)[10][CHAR_DATA_CHAR_INDEX]).eql('¥'); + expect(term.buffer.lines.get(0)[11][CHAR_DATA_CHAR_INDEX]).eql(''); + expect(term.buffer.lines.get(0)[14][CHAR_DATA_CHAR_INDEX]).eql('¥'); + expect(term.buffer.lines.get(0)[15][CHAR_DATA_CHAR_INDEX]).eql(''); + expect(term.buffer.lines.get(0)[79][CHAR_DATA_CHAR_INDEX]).eql('3'); + }); + it('fullwidth - right border', () => { + term.write(Array(41).join('¥')); + term.buffer.x = 10; + term.buffer.y = 0; + term.insertMode = true; + term.write('a'); + expect(term.buffer.lines.get(0).length).eql(term.cols); + expect(term.buffer.lines.get(0)[10][CHAR_DATA_CHAR_INDEX]).eql('a'); + expect(term.buffer.lines.get(0)[11][CHAR_DATA_CHAR_INDEX]).eql('¥'); + expect(term.buffer.lines.get(0)[79][CHAR_DATA_CHAR_INDEX]).eql(' '); // fullwidth char got replaced + term.write('b'); + expect(term.buffer.lines.get(0).length).eql(term.cols); + expect(term.buffer.lines.get(0)[11][CHAR_DATA_CHAR_INDEX]).eql('b'); + expect(term.buffer.lines.get(0)[12][CHAR_DATA_CHAR_INDEX]).eql('¥'); + expect(term.buffer.lines.get(0)[79][CHAR_DATA_CHAR_INDEX]).eql(''); // empty cell after fullwidth + }); + }); +}); diff --git a/xterm.js/src/Terminal.ts b/xterm.js/src/Terminal.ts new file mode 100644 index 0000000..b4bb377 --- /dev/null +++ b/xterm.js/src/Terminal.ts @@ -0,0 +1,2263 @@ +/** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) + * @license MIT + * + * Originally forked from (with the author's permission): + * Fabrice Bellard's javascript vt100 for jslinux: + * http://bellard.org/jslinux/ + * Copyright (c) 2011 Fabrice Bellard + * The original design remains. The terminal itself + * has been extended to include xterm CSI codes, among + * other features. + * + * Terminal Emulation References: + * http://vt100.net/ + * http://invisible-island.net/xterm/ctlseqs/ctlseqs.txt + * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html + * http://invisible-island.net/vttest/ + * http://www.inwap.com/pdp10/ansicode.txt + * http://linux.die.net/man/4/console_codes + * http://linux.die.net/man/7/urxvt + */ + +import { BufferSet } from './BufferSet'; +import { Buffer, MAX_BUFFER_SIZE } from './Buffer'; +import { CompositionHelper } from './CompositionHelper'; +import { EventEmitter } from './EventEmitter'; +import { Viewport } from './Viewport'; +import { rightClickHandler, moveTextAreaUnderMouseCursor, pasteHandler, copyHandler } from './handlers/Clipboard'; +import { CircularList } from './utils/CircularList'; +import { C0 } from './EscapeSequences'; +import { InputHandler } from './InputHandler'; +import { Parser } from './Parser'; +import { Renderer } from './renderer/Renderer'; +import { Linkifier } from './Linkifier'; +import { SelectionManager } from './SelectionManager'; +import { CharMeasure } from './utils/CharMeasure'; +import * as Browser from './utils/Browser'; +import { MouseHelper } from './utils/MouseHelper'; +import { CHARSETS } from './Charsets'; +import { CustomKeyEventHandler, Charset, LinkMatcherHandler, LinkMatcherValidationCallback, CharData, LineData } from './Types'; +import { ITerminal, IBrowser, ITerminalOptions, IInputHandlingTerminal, ILinkMatcherOptions, IViewport, ICompositionHelper, ITheme, ILinkifier } from './Interfaces'; +import { BellSound } from './utils/Sounds'; +import { DEFAULT_ANSI_COLORS } from './renderer/ColorManager'; +import { IMouseZoneManager } from './input/Interfaces'; +import { MouseZoneManager } from './input/MouseZoneManager'; +import { initialize as initializeCharAtlas } from './renderer/CharAtlas'; +import { IRenderer } from './renderer/Interfaces'; + +// Let it work inside Node.js for automated testing purposes. +const document = (typeof window !== 'undefined') ? window.document : null; + +/** + * The amount of write requests to queue before sending an XOFF signal to the + * pty process. This number must be small in order for ^C and similar sequences + * to be responsive. + */ +const WRITE_BUFFER_PAUSE_THRESHOLD = 5; + +/** + * The number of writes to perform in a single batch before allowing the + * renderer to catch up with a 0ms setTimeout. + */ +const WRITE_BATCH_SIZE = 300; + +const DEFAULT_OPTIONS: ITerminalOptions = { + cols: 80, + rows: 24, + convertEol: false, + termName: 'xterm', + cursorBlink: false, + cursorStyle: 'block', + bellSound: BellSound, + bellStyle: 'none', + enableBold: true, + fontFamily: 'courier-new, courier, monospace', + fontSize: 15, + lineHeight: 1.0, + letterSpacing: 0, + scrollback: 1000, + screenKeys: false, + debug: false, + cancelEvents: false, + disableStdin: false, + useFlowControl: false, + allowTransparency: false, + tabStopWidth: 8, + theme: null + // programFeatures: false, + // focusKeys: false, +}; + +export class Terminal extends EventEmitter implements ITerminal, IInputHandlingTerminal { + public textarea: HTMLTextAreaElement; + public element: HTMLElement; + + /** + * The HTMLElement that the terminal is created in, set by Terminal.open. + */ + private parent: HTMLElement; + private context: Window; + private document: Document; + private body: HTMLBodyElement; + private viewportScrollArea: HTMLElement; + private viewportElement: HTMLElement; + private helperContainer: HTMLElement; + private compositionView: HTMLElement; + private charSizeStyleElement: HTMLStyleElement; + private bellAudioElement: HTMLAudioElement; + private visualBellTimer: number; + + public browser: IBrowser = Browser; + + public options: ITerminalOptions; + private colors: any; + + // TODO: This can be changed to an enum or boolean, 0 and 1 seem to be the only options + public cursorState: number; + public cursorHidden: boolean; + public convertEol: boolean; + + private sendDataQueue: string; + private customKeyEventHandler: CustomKeyEventHandler; + + // modes + public applicationKeypad: boolean; + public applicationCursor: boolean; + public originMode: boolean; + public insertMode: boolean; + public wraparoundMode: boolean; // defaults: xterm - true, vt100 - false + public bracketedPasteMode: boolean; + + // charset + // The current charset + public charset: Charset; + public gcharset: number; + public glevel: number; + public charsets: Charset[]; + + // mouse properties + private decLocator: boolean; // This is unstable and never set + public x10Mouse: boolean; + public vt200Mouse: boolean; + private vt300Mouse: boolean; // This is unstable and never set + public normalMouse: boolean; + public mouseEvents: boolean; + public sendFocus: boolean; + public utfMouse: boolean; + public sgrMouse: boolean; + public urxvtMouse: boolean; + + // misc + private refreshStart: number; + private refreshEnd: number; + public savedCols: number; + + // stream + private readable: boolean; + private writable: boolean; + + public defAttr: number; + public curAttr: number; + + public params: (string | number)[]; + public currentParam: string | number; + public prefix: string; + public postfix: string; + + // user input states + public writeBuffer: string[]; + private writeInProgress: boolean; + + /** + * Whether _xterm.js_ sent XOFF in order to catch up with the pty process. + * This is a distinct state from writeStopped so that if the user requested + * XOFF via ^S that it will not automatically resume when the writeBuffer goes + * below threshold. + */ + private xoffSentToCatchUp: boolean; + + /** Whether writing has been stopped as a result of XOFF */ + private writeStopped: boolean; + + // leftover surrogate high from previous write invocation + private surrogate_high: string; + + // Store if user went browsing history in scrollback + private userScrolling: boolean; + + private inputHandler: InputHandler; + private parser: Parser; + public renderer: IRenderer; + public selectionManager: SelectionManager; + public linkifier: ILinkifier; + public buffers: BufferSet; + public buffer: Buffer; + public viewport: IViewport; + private compositionHelper: ICompositionHelper; + public charMeasure: CharMeasure; + private _mouseZoneManager: IMouseZoneManager; + public mouseHelper: MouseHelper; + + public cols: number; + public rows: number; + + /** + * Creates a new `Terminal` object. + * + * @param {object} options An object containing a set of options, the available options are: + * - `cursorBlink` (boolean): Whether the terminal cursor blinks + * - `cols` (number): The number of columns of the terminal (horizontal size) + * - `rows` (number): The number of rows of the terminal (vertical size) + * + * @public + * @class Xterm Xterm + * @alias module:xterm/src/xterm + */ + constructor( + options: ITerminalOptions = {} + ) { + super(); + this.options = options; + this.setup(); + } + + private setup(): void { + Object.keys(DEFAULT_OPTIONS).forEach((key) => { + if (this.options[key] == null) { + this.options[key] = DEFAULT_OPTIONS[key]; + } + // TODO: We should move away from duplicate options on the Terminal object + this[key] = this.options[key]; + }); + + // this.context = options.context || window; + // this.document = options.document || document; + // TODO: WHy not document.body? + this.parent = document ? document.body : null; + + this.cols = this.options.cols; + this.rows = this.options.rows; + + if (this.options.handler) { + this.on('data', this.options.handler); + } + + this.cursorState = 0; + this.cursorHidden = false; + this.sendDataQueue = ''; + this.customKeyEventHandler = null; + + // modes + this.applicationKeypad = false; + this.applicationCursor = false; + this.originMode = false; + this.insertMode = false; + this.wraparoundMode = true; // defaults: xterm - true, vt100 - false + this.bracketedPasteMode = false; + + // charset + this.charset = null; + this.gcharset = null; + this.glevel = 0; + // TODO: Can this be just []? + this.charsets = [null]; + + this.readable = true; + this.writable = true; + + this.defAttr = (0 << 18) | (257 << 9) | (256 << 0); + this.curAttr = (0 << 18) | (257 << 9) | (256 << 0); + + this.params = []; + this.currentParam = 0; + this.prefix = ''; + this.postfix = ''; + + // user input states + this.writeBuffer = []; + this.writeInProgress = false; + + this.xoffSentToCatchUp = false; + this.writeStopped = false; + this.surrogate_high = ''; + this.userScrolling = false; + + this.inputHandler = new InputHandler(this); + this.parser = new Parser(this.inputHandler, this); + // Reuse renderer if the Terminal is being recreated via a reset call. + this.renderer = this.renderer || null; + this.selectionManager = this.selectionManager || null; + this.linkifier = this.linkifier || new Linkifier(this); + this._mouseZoneManager = this._mouseZoneManager || null; + + // Create the terminal's buffers and set the current buffer + this.buffers = new BufferSet(this); + this.buffer = this.buffers.active; // Convenience shortcut; + this.buffers.on('activate', (buffer: Buffer) => { + this.buffer = buffer; + }); + + // Ensure the selection manager has the correct buffer + if (this.selectionManager) { + this.selectionManager.setBuffer(this.buffer); + } + } + + /** + * back_color_erase feature for xterm. + */ + public eraseAttr(): number { + // if (this.is('screen')) return this.defAttr; + return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff); + } + + /** + * Focus the terminal. Delegates focus handling to the terminal's DOM element. + */ + public focus(): void { + if (this.textarea) { + this.textarea.focus(); + } + } + + public get isFocused(): boolean { + return document.activeElement === this.textarea; + } + + /** + * Retrieves an option's value from the terminal. + * @param {string} key The option key. + */ + public getOption(key: string): any { + if (!(key in DEFAULT_OPTIONS)) { + throw new Error('No option with key "' + key + '"'); + } + + if (typeof this.options[key] !== 'undefined') { + return this.options[key]; + } + + return this[key]; + } + + /** + * Sets an option on the terminal. + * @param {string} key The option key. + * @param {any} value The option value. + */ + public setOption(key: string, value: any): void { + if (!(key in DEFAULT_OPTIONS)) { + throw new Error('No option with key "' + key + '"'); + } + switch (key) { + case 'bellStyle': + if (!value) { + value = 'none'; + } + break; + case 'cursorStyle': + if (!value) { + value = 'block'; + } + break; + case 'lineHeight': + if (value < 1) { + console.warn(`${key} cannot be less than 1, value: ${value}`); + return; + } + case 'tabStopWidth': + if (value < 1) { + console.warn(`${key} cannot be less than 1, value: ${value}`); + return; + } + break; + case 'theme': + // If open has been called we do not want to set options.theme as the + // source of truth is owned by the renderer. + if (this.renderer) { + this._setTheme(value); + return; + } + break; + case 'scrollback': + value = Math.min(value, MAX_BUFFER_SIZE); + + if (value < 0) { + console.warn(`${key} cannot be less than 0, value: ${value}`); + return; + } + if (this.options[key] !== value) { + const newBufferLength = this.rows + value; + if (this.buffer.lines.length > newBufferLength) { + const amountToTrim = this.buffer.lines.length - newBufferLength; + const needsRefresh = (this.buffer.ydisp - amountToTrim < 0); + this.buffer.lines.trimStart(amountToTrim); + this.buffer.ybase = Math.max(this.buffer.ybase - amountToTrim, 0); + this.buffer.ydisp = Math.max(this.buffer.ydisp - amountToTrim, 0); + if (needsRefresh) { + this.refresh(0, this.rows - 1); + } + } + } + break; + } + this[key] = value; + this.options[key] = value; + switch (key) { + case 'fontFamily': + case 'fontSize': + // When the font changes the size of the cells may change which requires a renderer clear + this.renderer.clear(); + this.charMeasure.measure(this.options); + break; + case 'enableBold': + case 'letterSpacing': + case 'lineHeight': + // When the font changes the size of the cells may change which requires a renderer clear + this.renderer.clear(); + this.renderer.onResize(this.cols, this.rows, false); + this.refresh(0, this.rows - 1); + // this.charMeasure.measure(this.options); + case 'scrollback': + this.buffers.resize(this.cols, this.rows); + this.viewport.syncScrollArea(); + break; + case 'tabStopWidth': this.buffers.setupTabStops(); break; + case 'bellSound': + case 'bellStyle': this.syncBellSound(); break; + } + // Inform renderer of changes + if (this.renderer) { + this.renderer.onOptionsChanged(); + } + } + + /** + * Binds the desired focus behavior on a given terminal object. + */ + private _onTextAreaFocus(): void { + if (this.sendFocus) { + this.send(C0.ESC + '[I'); + } + this.element.classList.add('focus'); + this.showCursor(); + this.emit('focus'); + }; + + /** + * Blur the terminal, calling the blur function on the terminal's underlying + * textarea. + */ + public blur(): void { + return this.textarea.blur(); + } + + /** + * Binds the desired blur behavior on a given terminal object. + */ + private _onTextAreaBlur(): void { + this.refresh(this.buffer.y, this.buffer.y); + if (this.sendFocus) { + this.send(C0.ESC + '[O'); + } + this.element.classList.remove('focus'); + this.emit('blur'); + } + + /** + * Initialize default behavior + */ + private initGlobal(): void { + this.bindKeys(); + + // Bind clipboard functionality + on(this.element, 'copy', (event: ClipboardEvent) => { + // If mouse events are active it means the selection manager is disabled and + // copy should be handled by the host program. + if (!this.hasSelection()) { + return; + } + copyHandler(event, this, this.selectionManager); + }); + const pasteHandlerWrapper = event => pasteHandler(event, this); + on(this.textarea, 'paste', pasteHandlerWrapper); + on(this.element, 'paste', pasteHandlerWrapper); + + // Handle right click context menus + if (Browser.isFirefox) { + // Firefox doesn't appear to fire the contextmenu event on right click + on(this.element, 'mousedown', (event: MouseEvent) => { + if (event.button === 2) { + rightClickHandler(event, this.textarea, this.selectionManager); + } + }); + } else { + on(this.element, 'contextmenu', (event: MouseEvent) => { + rightClickHandler(event, this.textarea, this.selectionManager); + }); + } + + // Move the textarea under the cursor when middle clicking on Linux to ensure + // middle click to paste selection works. This only appears to work in Chrome + // at the time is writing. + if (Browser.isLinux) { + // Use auxclick event over mousedown the latter doesn't seem to work. Note + // that the regular click event doesn't fire for the middle mouse button. + on(this.element, 'auxclick', (event: MouseEvent) => { + if (event.button === 1) { + moveTextAreaUnderMouseCursor(event, this.textarea); + } + }); + } + } + + /** + * Apply key handling to the terminal + */ + private bindKeys(): void { + const self = this; + on(this.element, 'keydown', function (ev: KeyboardEvent): void { + if (document.activeElement !== this) { + return; + } + self._keyDown(ev); + }, true); + + on(this.element, 'keypress', function (ev: KeyboardEvent): void { + if (document.activeElement !== this) { + return; + } + self._keyPress(ev); + }, true); + + on(this.element, 'keyup', (ev: KeyboardEvent) => { + if (!wasMondifierKeyOnlyEvent(ev)) { + this.focus(); + } + }, true); + + on(this.textarea, 'keydown', (ev: KeyboardEvent) => { + this._keyDown(ev); + }, true); + + on(this.textarea, 'keypress', (ev: KeyboardEvent) => { + this._keyPress(ev); + // Truncate the textarea's value, since it is not needed + this.textarea.value = ''; + }, true); + + on(this.textarea, 'compositionstart', () => this.compositionHelper.compositionstart()); + on(this.textarea, 'compositionupdate', (e: CompositionEvent) => this.compositionHelper.compositionupdate(e)); + on(this.textarea, 'compositionend', () => this.compositionHelper.compositionend()); + this.on('refresh', () => this.compositionHelper.updateCompositionElements()); + this.on('refresh', (data) => this.queueLinkification(data.start, data.end)); + } + + /** + * Opens the terminal within an element. + * + * @param {HTMLElement} parent The element to create the terminal within. + */ + public open(parent: HTMLElement): void { + let i = 0; + let div; + + this.parent = parent || this.parent; + + if (!this.parent) { + throw new Error('Terminal requires a parent element.'); + } + + // Grab global elements + this.context = this.parent.ownerDocument.defaultView; + this.document = this.parent.ownerDocument; + this.body = this.document.body; + + initializeCharAtlas(this.document, this.options.allowTransparency); + + // Create main element container + this.element = this.document.createElement('div'); + this.element.classList.add('terminal'); + this.element.classList.add('xterm'); + this.element.setAttribute('tabindex', '0'); + this.parent.appendChild(this.element); + + // Performance: Use a document fragment to build the terminal + // viewport and helper elements detached from the DOM + const fragment = document.createDocumentFragment(); + this.viewportElement = document.createElement('div'); + this.viewportElement.classList.add('xterm-viewport'); + fragment.appendChild(this.viewportElement); + this.viewportScrollArea = document.createElement('div'); + this.viewportScrollArea.classList.add('xterm-scroll-area'); + this.viewportElement.appendChild(this.viewportScrollArea); + + this._mouseZoneManager = new MouseZoneManager(this); + this.on('scroll', () => this._mouseZoneManager.clearAll()); + this.linkifier.attachToDom(this._mouseZoneManager); + + // Create the container that will hold helpers like the textarea for + // capturing DOM Events. Then produce the helpers. + this.helperContainer = document.createElement('div'); + this.helperContainer.classList.add('xterm-helpers'); + fragment.appendChild(this.helperContainer); + + this.textarea = document.createElement('textarea'); + this.textarea.classList.add('xterm-helper-textarea'); + this.textarea.setAttribute('autocorrect', 'off'); + this.textarea.setAttribute('autocapitalize', 'off'); + this.textarea.setAttribute('spellcheck', 'false'); + this.textarea.tabIndex = 0; + this.textarea.addEventListener('focus', () => this._onTextAreaFocus()); + this.textarea.addEventListener('blur', () => this._onTextAreaBlur()); + this.helperContainer.appendChild(this.textarea); + + this.compositionView = document.createElement('div'); + this.compositionView.classList.add('composition-view'); + this.compositionHelper = new CompositionHelper(this.textarea, this.compositionView, this); + this.helperContainer.appendChild(this.compositionView); + + this.charSizeStyleElement = document.createElement('style'); + this.helperContainer.appendChild(this.charSizeStyleElement); + this.charMeasure = new CharMeasure(document, this.helperContainer); + + // Preload audio, this relied on helperContainer + this.syncBellSound(); + + // Performance: Add viewport and helper elements from the fragment + this.element.appendChild(fragment); + + this.renderer = new Renderer(this, this.options.theme); + this.options.theme = null; + this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure); + this.viewport.onThemeChanged(this.renderer.colorManager.colors); + + this.on('cursormove', () => this.renderer.onCursorMove()); + this.on('resize', () => this.renderer.onResize(this.cols, this.rows, false)); + this.on('blur', () => this.renderer.onBlur()); + this.on('focus', () => this.renderer.onFocus()); + this.charMeasure.on('charsizechanged', () => this.renderer.onResize(this.cols, this.rows, true)); + this.renderer.on('resize', (dimensions) => this.viewport.syncScrollArea()); + + this.selectionManager = new SelectionManager(this, this.buffer, this.charMeasure); + this.element.addEventListener('mousedown', (e: MouseEvent) => this.selectionManager.onMouseDown(e)); + this.selectionManager.on('refresh', data => this.renderer.onSelectionChanged(data.start, data.end)); + this.selectionManager.on('newselection', text => { + // If there's a new selection, put it into the textarea, focus and select it + // in order to register it as a selection on the OS. This event is fired + // only on Linux to enable middle click to paste selection. + this.textarea.value = text; + this.textarea.focus(); + this.textarea.select(); + }); + this.on('scroll', () => { + this.viewport.syncScrollArea(); + this.selectionManager.refresh(); + }); + this.viewportElement.addEventListener('scroll', () => this.selectionManager.refresh()); + + this.mouseHelper = new MouseHelper(this.renderer); + + // Measure the character size + this.charMeasure.measure(this.options); + + // Setup loop that draws to screen + this.refresh(0, this.rows - 1); + + // Initialize global actions that need to be taken on the document. + this.initGlobal(); + + // Listen for mouse events and translate + // them into terminal mouse protocols. + this.bindMouse(); + + } + + /** + * Sets the theme on the renderer. The renderer must have been initialized. + * @param theme The theme to ste. + */ + private _setTheme(theme: ITheme): void { + const colors = this.renderer.setTheme(theme); + if (this.viewport) { + this.viewport.onThemeChanged(colors); + } + } + + /** + * Apply the provided addon on the `Terminal` class. + * @param addon The addon to apply. + */ + public static applyAddon(addon: any): void { + addon.apply(Terminal); + } + + /** + * XTerm mouse events + * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking + * To better understand these + * the xterm code is very helpful: + * Relevant files: + * button.c, charproc.c, misc.c + * Relevant functions in xterm/button.c: + * BtnCode, EmitButtonCode, EditorButton, SendMousePosition + */ + public bindMouse(): void { + const el = this.element; + const self = this; + let pressed = 32; + + // mouseup, mousedown, wheel + // left click: ^[[M 3<^[[M#3< + // wheel up: ^[[M`3> + function sendButton(ev: MouseEvent | WheelEvent): void { + let button; + let pos; + + // get the xterm-style button + button = getButton(ev); + + // get mouse coordinates + pos = self.mouseHelper.getRawByteCoords(ev, self.element, self.charMeasure, self.options.lineHeight, self.cols, self.rows); + if (!pos) return; + + sendEvent(button, pos); + + switch ((ev).overrideType || ev.type) { + case 'mousedown': + pressed = button; + break; + case 'mouseup': + // keep it at the left + // button, just in case. + pressed = 32; + break; + case 'wheel': + // nothing. don't + // interfere with + // `pressed`. + break; + } + } + + // motion example of a left click: + // ^[[M 3<^[[M@4<^[[M@5<^[[M@6<^[[M@7<^[[M#7< + function sendMove(ev: MouseEvent): void { + let button = pressed; + let pos = self.mouseHelper.getRawByteCoords(ev, self.element, self.charMeasure, self.options.lineHeight, self.cols, self.rows); + if (!pos) return; + + // buttons marked as motions + // are incremented by 32 + button += 32; + + sendEvent(button, pos); + } + + // encode button and + // position to characters + function encode(data: number[], ch: number): void { + if (!self.utfMouse) { + if (ch === 255) { + data.push(0); + return; + } + if (ch > 127) ch = 127; + data.push(ch); + } else { + if (ch === 2047) { + data.push(0); + return; + } + if (ch < 127) { + data.push(ch); + } else { + if (ch > 2047) ch = 2047; + data.push(0xC0 | (ch >> 6)); + data.push(0x80 | (ch & 0x3F)); + } + } + } + + // send a mouse event: + // regular/utf8: ^[[M Cb Cx Cy + // urxvt: ^[[ Cb ; Cx ; Cy M + // sgr: ^[[ Cb ; Cx ; Cy M/m + // vt300: ^[[ 24(1/3/5)~ [ Cx , Cy ] \r + // locator: CSI P e ; P b ; P r ; P c ; P p & w + function sendEvent(button: number, pos: {x: number, y: number}): void { + // self.emit('mouse', { + // x: pos.x - 32, + // y: pos.x - 32, + // button: button + // }); + + if (self.vt300Mouse) { + // NOTE: Unstable. + // http://www.vt100.net/docs/vt3xx-gp/chapter15.html + button &= 3; + pos.x -= 32; + pos.y -= 32; + let data = C0.ESC + '[24'; + if (button === 0) data += '1'; + else if (button === 1) data += '3'; + else if (button === 2) data += '5'; + else if (button === 3) return; + else data += '0'; + data += '~[' + pos.x + ',' + pos.y + ']\r'; + self.send(data); + return; + } + + if (self.decLocator) { + // NOTE: Unstable. + button &= 3; + pos.x -= 32; + pos.y -= 32; + if (button === 0) button = 2; + else if (button === 1) button = 4; + else if (button === 2) button = 6; + else if (button === 3) button = 3; + self.send(C0.ESC + '[' + + button + + ';' + + (button === 3 ? 4 : 0) + + ';' + + pos.y + + ';' + + pos.x + + ';' + // Not sure what page is meant to be + + (pos).page || 0 + + '&w'); + return; + } + + if (self.urxvtMouse) { + pos.x -= 32; + pos.y -= 32; + pos.x++; + pos.y++; + self.send(C0.ESC + '[' + button + ';' + pos.x + ';' + pos.y + 'M'); + return; + } + + if (self.sgrMouse) { + pos.x -= 32; + pos.y -= 32; + self.send(C0.ESC + '[<' + + (((button & 3) === 3 ? button & ~3 : button) - 32) + + ';' + + pos.x + + ';' + + pos.y + + ((button & 3) === 3 ? 'm' : 'M')); + return; + } + + let data: number[] = []; + + encode(data, button); + encode(data, pos.x); + encode(data, pos.y); + + self.send(C0.ESC + '[M' + String.fromCharCode.apply(String, data)); + } + + function getButton(ev: MouseEvent): number { + let button; + let shift; + let meta; + let ctrl; + let mod; + + // two low bits: + // 0 = left + // 1 = middle + // 2 = right + // 3 = release + // wheel up/down: + // 1, and 2 - with 64 added + switch ((ev).overrideType || ev.type) { + case 'mousedown': + button = ev.button != null + ? +ev.button + : ev.which != null + ? ev.which - 1 + : null; + + if (Browser.isMSIE) { + button = button === 1 ? 0 : button === 4 ? 1 : button; + } + break; + case 'mouseup': + button = 3; + break; + case 'DOMMouseScroll': + button = ev.detail < 0 + ? 64 + : 65; + break; + case 'wheel': + button = (ev).wheelDeltaY > 0 + ? 64 + : 65; + break; + } + + // next three bits are the modifiers: + // 4 = shift, 8 = meta, 16 = control + shift = ev.shiftKey ? 4 : 0; + meta = ev.metaKey ? 8 : 0; + ctrl = ev.ctrlKey ? 16 : 0; + mod = shift | meta | ctrl; + + // no mods + if (self.vt200Mouse) { + // ctrl only + mod &= ctrl; + } else if (!self.normalMouse) { + mod = 0; + } + + // increment to SP + button = (32 + (mod << 2)) + button; + + return button; + } + + on(el, 'mousedown', (ev: MouseEvent) => { + + // Prevent the focus on the textarea from getting lost + // and make sure we get focused on mousedown + ev.preventDefault(); + this.focus(); + + // Don't send the mouse button to the pty if mouse events are disabled or + // if the selection manager is having selection forced (ie. a modifier is + // held). + if (!this.mouseEvents || this.selectionManager.shouldForceSelection(ev)) { + return; + } + + // send the button + sendButton(ev); + + // fix for odd bug + // if (this.vt200Mouse && !this.normalMouse) { + if (this.vt200Mouse) { + (ev).overrideType = 'mouseup'; + sendButton(ev); + return this.cancel(ev); + } + + // bind events + if (this.normalMouse) on(this.document, 'mousemove', sendMove); + + // x10 compatibility mode can't send button releases + if (!this.x10Mouse) { + const handler = (ev: MouseEvent) => { + sendButton(ev); + // TODO: Seems dangerous calling this on document? + if (this.normalMouse) off(this.document, 'mousemove', sendMove); + off(this.document, 'mouseup', handler); + return this.cancel(ev); + }; + // TODO: Seems dangerous calling this on document? + on(this.document, 'mouseup', handler); + } + + return this.cancel(ev); + }); + + // if (this.normalMouse) { + // on(this.document, 'mousemove', sendMove); + // } + + on(el, 'wheel', (ev: WheelEvent) => { + if (!this.mouseEvents) return; + if (this.x10Mouse || this.vt300Mouse || this.decLocator) return; + sendButton(ev); + ev.preventDefault(); + }); + + // allow wheel scrolling in + // the shell for example + on(el, 'wheel', (ev: WheelEvent) => { + if (this.mouseEvents) return; + this.viewport.onWheel(ev); + return this.cancel(ev); + }); + + on(el, 'touchstart', (ev: TouchEvent) => { + if (this.mouseEvents) return; + this.viewport.onTouchStart(ev); + return this.cancel(ev); + }); + + on(el, 'touchmove', (ev: TouchEvent) => { + if (this.mouseEvents) return; + this.viewport.onTouchMove(ev); + return this.cancel(ev); + }); + } + + /** + * Destroys the terminal. + */ + public destroy(): void { + super.destroy(); + this.readable = false; + this.writable = false; + this.handler = () => {}; + this.write = () => {}; + if (this.element && this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + } + // this.emit('close'); + } + + /** + * Tells the renderer to refresh terminal content between two rows (inclusive) at the next + * opportunity. + * @param {number} start The row to start from (between 0 and this.rows - 1). + * @param {number} end The row to end at (between start and this.rows - 1). + */ + public refresh(start: number, end: number): void { + if (this.renderer) { + this.renderer.queueRefresh(start, end); + } + } + + /** + * Queues linkification for the specified rows. + * @param {number} start The row to start from (between 0 and this.rows - 1). + * @param {number} end The row to end at (between start and this.rows - 1). + */ + private queueLinkification(start: number, end: number): void { + if (this.linkifier) { + this.linkifier.linkifyRows(start, end); + } + } + + /** + * Display the cursor element + */ + public showCursor(): void { + if (!this.cursorState) { + this.cursorState = 1; + this.refresh(this.buffer.y, this.buffer.y); + } + } + + /** + * Scroll the terminal down 1 row, creating a blank line. + * @param isWrapped Whether the new line is wrapped from the previous line. + */ + public scroll(isWrapped?: boolean): void { + const newLine = this.blankLine(undefined, isWrapped); + const topRow = this.buffer.ybase + this.buffer.scrollTop; + let bottomRow = this.buffer.ybase + this.buffer.scrollBottom; + + if (this.buffer.scrollTop === 0) { + // Determine whether the buffer is going to be trimmed after insertion. + const willBufferBeTrimmed = this.buffer.lines.length === this.buffer.lines.maxLength; + + // Insert the line using the fastest method + if (bottomRow === this.buffer.lines.length - 1) { + this.buffer.lines.push(newLine); + } else { + this.buffer.lines.splice(bottomRow + 1, 0, newLine); + } + + // Only adjust ybase and ydisp when the buffer is not trimmed + if (!willBufferBeTrimmed) { + this.buffer.ybase++; + // Only scroll the ydisp with ybase if the user has not scrolled up + if (!this.userScrolling) { + this.buffer.ydisp++; + } + } else { + // When the buffer is full and the user has scrolled up, keep the text + // stable unless ydisp is right at the top + if (this.userScrolling) { + this.buffer.ydisp = Math.max(this.buffer.ydisp - 1, 0); + } + } + } else { + // scrollTop is non-zero which means no line will be going to the + // scrollback, instead we can just shift them in-place. + const scrollRegionHeight = bottomRow - topRow + 1/*as it's zero-based*/; + this.buffer.lines.shiftElements(topRow + 1, scrollRegionHeight - 1, -1); + this.buffer.lines.set(bottomRow, newLine); + } + + // Move the viewport to the bottom of the buffer unless the user is + // scrolling. + if (!this.userScrolling) { + this.buffer.ydisp = this.buffer.ybase; + } + + // Flag rows that need updating + this.updateRange(this.buffer.scrollTop); + this.updateRange(this.buffer.scrollBottom); + + /** + * This event is emitted whenever the terminal is scrolled. + * The one parameter passed is the new y display position. + * + * @event scroll + */ + this.emit('scroll', this.buffer.ydisp); + } + + /** + * Scroll the display of the terminal + * @param {number} disp The number of lines to scroll down (negative scroll up). + * @param {boolean} suppressScrollEvent Don't emit the scroll event as scrollLines. This is used + * to avoid unwanted events being handled by the viewport when the event was triggered from the + * viewport originally. + */ + public scrollLines(disp: number, suppressScrollEvent?: boolean): void { + if (disp < 0) { + if (this.buffer.ydisp === 0) { + return; + } + this.userScrolling = true; + } else if (disp + this.buffer.ydisp >= this.buffer.ybase) { + this.userScrolling = false; + } + + const oldYdisp = this.buffer.ydisp; + this.buffer.ydisp = Math.max(Math.min(this.buffer.ydisp + disp, this.buffer.ybase), 0); + + // No change occurred, don't trigger scroll/refresh + if (oldYdisp === this.buffer.ydisp) { + return; + } + + if (!suppressScrollEvent) { + this.emit('scroll', this.buffer.ydisp); + } + + this.refresh(0, this.rows - 1); + } + + /** + * Scroll the display of the terminal by a number of pages. + * @param {number} pageCount The number of pages to scroll (negative scrolls up). + */ + public scrollPages(pageCount: number): void { + this.scrollLines(pageCount * (this.rows - 1)); + } + + /** + * Scrolls the display of the terminal to the top. + */ + public scrollToTop(): void { + this.scrollLines(-this.buffer.ydisp); + } + + /** + * Scrolls the display of the terminal to the bottom. + */ + public scrollToBottom(): void { + this.scrollLines(this.buffer.ybase - this.buffer.ydisp); + } + + /** + * Writes text to the terminal. + * @param {string} data The text to write to the terminal. + */ + public write(data: string): void { + this.writeBuffer.push(data); + + // Send XOFF to pause the pty process if the write buffer becomes too large so + // xterm.js can catch up before more data is sent. This is necessary in order + // to keep signals such as ^C responsive. + if (this.options.useFlowControl && !this.xoffSentToCatchUp && this.writeBuffer.length >= WRITE_BUFFER_PAUSE_THRESHOLD) { + // XOFF - stop pty pipe + // XON will be triggered by emulator before processing data chunk + this.send(C0.DC3); + this.xoffSentToCatchUp = true; + } + + if (!this.writeInProgress && this.writeBuffer.length > 0) { + // Kick off a write which will write all data in sequence recursively + this.writeInProgress = true; + // Kick off an async innerWrite so more writes can come in while processing data + setTimeout(() => { + this.innerWrite(); + }); + } + } + + private innerWrite(): void { + const writeBatch = this.writeBuffer.splice(0, WRITE_BATCH_SIZE); + while (writeBatch.length > 0) { + const data = writeBatch.shift(); + + // If XOFF was sent in order to catch up with the pty process, resume it if + // the writeBuffer is empty to allow more data to come in. + if (this.xoffSentToCatchUp && writeBatch.length === 0 && this.writeBuffer.length === 0) { + this.send(C0.DC1); + this.xoffSentToCatchUp = false; + } + + this.refreshStart = this.buffer.y; + this.refreshEnd = this.buffer.y; + + // HACK: Set the parser state based on it's state at the time of return. + // This works around the bug #662 which saw the parser state reset in the + // middle of parsing escape sequence in two chunks. For some reason the + // state of the parser resets to 0 after exiting parser.parse. This change + // just sets the state back based on the correct return statement. + const state = this.parser.parse(data); + this.parser.setState(state); + + this.updateRange(this.buffer.y); + this.refresh(this.refreshStart, this.refreshEnd); + } + if (this.writeBuffer.length > 0) { + // Allow renderer to catch up before processing the next batch + setTimeout(() => this.innerWrite(), 0); + } else { + this.writeInProgress = false; + } + } + + /** + * Writes text to the terminal, followed by a break line character (\n). + * @param {string} data The text to write to the terminal. + */ + public writeln(data: string): void { + this.write(data + '\r\n'); + } + + /** + * Attaches a custom key event handler which is run before keys are processed, + * giving consumers of xterm.js ultimate control as to what keys should be + * processed by the terminal and what keys should not. + * @param customKeyEventHandler The custom KeyboardEvent handler to attach. + * This is a function that takes a KeyboardEvent, allowing consumers to stop + * propogation and/or prevent the default action. The function returns whether + * the event should be processed by xterm.js. + */ + public attachCustomKeyEventHandler(customKeyEventHandler: CustomKeyEventHandler): void { + this.customKeyEventHandler = customKeyEventHandler; + } + + /** + * Attaches a http(s) link handler, forcing web links to behave differently to + * regular tags. This will trigger a refresh as links potentially need to be + * reconstructed. Calling this with null will remove the handler. + * @param handler The handler callback function. + */ + public setHypertextLinkHandler(handler: LinkMatcherHandler): void { + if (!this.linkifier) { + throw new Error('Cannot attach a hypertext link handler before Terminal.open is called'); + } + this.linkifier.setHypertextLinkHandler(handler); + // Refresh to force links to refresh + this.refresh(0, this.rows - 1); + } + + /** + * Attaches a validation callback for hypertext links. This is useful to use + * validation logic or to do something with the link's element and url. + * @param callback The callback to use, this can + * be cleared with null. + */ + public setHypertextValidationCallback(callback: LinkMatcherValidationCallback): void { + if (!this.linkifier) { + throw new Error('Cannot attach a hypertext validation callback before Terminal.open is called'); + } + this.linkifier.setHypertextValidationCallback(callback); + // // Refresh to force links to refresh + this.refresh(0, this.rows - 1); + } + + /** + * Registers a link matcher, allowing custom link patterns to be matched and + * handled. + * @param regex The regular expression to search for, specifically + * this searches the textContent of the rows. You will want to use \s to match + * a space ' ' character for example. + * @param handler The callback when the link is called. + * @param options Options for the link matcher. + * @return The ID of the new matcher, this can be used to deregister. + */ + public registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options?: ILinkMatcherOptions): number { + if (this.linkifier) { + const matcherId = this.linkifier.registerLinkMatcher(regex, handler, options); + this.refresh(0, this.rows - 1); + return matcherId; + } + return 0; + } + + /** + * Deregisters a link matcher if it has been registered. + * @param matcherId The link matcher's ID (returned after register) + */ + public deregisterLinkMatcher(matcherId: number): void { + if (this.linkifier) { + if (this.linkifier.deregisterLinkMatcher(matcherId)) { + this.refresh(0, this.rows - 1); + } + } + } + + /** + * Gets whether the terminal has an active selection. + */ + public hasSelection(): boolean { + return this.selectionManager ? this.selectionManager.hasSelection : false; + } + + /** + * Gets the terminal's current selection, this is useful for implementing copy + * behavior outside of xterm.js. + */ + public getSelection(): string { + return this.selectionManager ? this.selectionManager.selectionText : ''; + } + + /** + * Clears the current terminal selection. + */ + public clearSelection(): void { + if (this.selectionManager) { + this.selectionManager.clearSelection(); + } + } + + /** + * Selects all text within the terminal. + */ + public selectAll(): void { + if (this.selectionManager) { + this.selectionManager.selectAll(); + } + } + + /** + * Handle a keydown event + * Key Resources: + * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent + * @param {KeyboardEvent} ev The keydown event to be handled. + */ + protected _keyDown(ev: KeyboardEvent): boolean { + if (this.customKeyEventHandler && this.customKeyEventHandler(ev) === false) { + return false; + } + + if (!this.compositionHelper.keydown(ev)) { + if (this.buffer.ybase !== this.buffer.ydisp) { + this.scrollToBottom(); + } + return false; + } + + const result = this._evaluateKeyEscapeSequence(ev); + + if (result.key === C0.DC3) { // XOFF + this.writeStopped = true; + } else if (result.key === C0.DC1) { // XON + this.writeStopped = false; + } + + if (result.scrollLines) { + this.scrollLines(result.scrollLines); + return this.cancel(ev, true); + } + + if (isThirdLevelShift(this.browser, ev)) { + return true; + } + + if (result.cancel) { + // The event is canceled at the end already, is this necessary? + this.cancel(ev, true); + } + + if (!result.key) { + return true; + } + + this.emit('keydown', ev); + this.emit('key', result.key, ev); + this.showCursor(); + this.handler(result.key); + + return this.cancel(ev, true); + } + + /** + * Returns an object that determines how a KeyboardEvent should be handled. The key of the + * returned value is the new key code to pass to the PTY. + * + * Reference: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html + * @param ev The keyboard event to be translated to key escape sequence. + */ + protected _evaluateKeyEscapeSequence(ev: KeyboardEvent): {cancel: boolean, key: string, scrollLines: number} { + const result: {cancel: boolean, key: string, scrollLines: number} = { + // Whether to cancel event propogation (NOTE: this may not be needed since the event is + // canceled at the end of keyDown + cancel: false, + // The new key even to emit + key: undefined, + // The number of characters to scroll, if this is defined it will cancel the event + scrollLines: undefined + }; + const modifiers = (ev.shiftKey ? 1 : 0) | (ev.altKey ? 2 : 0) | (ev.ctrlKey ? 4 : 0) | (ev.metaKey ? 8 : 0); + switch (ev.keyCode) { + case 0: + if (ev.key === 'UIKeyInputUpArrow') { + if (this.applicationCursor) { + result.key = C0.ESC + 'OA'; + } else { + result.key = C0.ESC + '[A'; + } + } + else if (ev.key === 'UIKeyInputLeftArrow') { + if (this.applicationCursor) { + result.key = C0.ESC + 'OD'; + } else { + result.key = C0.ESC + '[D'; + } + } + else if (ev.key === 'UIKeyInputRightArrow') { + if (this.applicationCursor) { + result.key = C0.ESC + 'OC'; + } else { + result.key = C0.ESC + '[C'; + } + } + else if (ev.key === 'UIKeyInputDownArrow') { + if (this.applicationCursor) { + result.key = C0.ESC + 'OB'; + } else { + result.key = C0.ESC + '[B'; + } + } + break; + case 8: + // backspace + if (ev.shiftKey) { + result.key = C0.BS; // ^H + break; + } else if (ev.altKey) { + result.key = C0.ESC + C0.DEL; // \e ^? + break; + } + result.key = C0.DEL; // ^? + break; + case 9: + // tab + if (ev.shiftKey) { + result.key = C0.ESC + '[Z'; + break; + } + result.key = C0.HT; + result.cancel = true; + break; + case 13: + // return/enter + result.key = C0.CR; + result.cancel = true; + break; + case 27: + // escape + result.key = C0.ESC; + result.cancel = true; + break; + case 37: + // left-arrow + if (modifiers) { + result.key = C0.ESC + '[1;' + (modifiers + 1) + 'D'; + // HACK: Make Alt + left-arrow behave like Ctrl + left-arrow: move one word backwards + // http://unix.stackexchange.com/a/108106 + // macOS uses different escape sequences than linux + if (result.key === C0.ESC + '[1;3D') { + result.key = (this.browser.isMac) ? C0.ESC + 'b' : C0.ESC + '[1;5D'; + } + } else if (this.applicationCursor) { + result.key = C0.ESC + 'OD'; + } else { + result.key = C0.ESC + '[D'; + } + break; + case 39: + // right-arrow + if (modifiers) { + result.key = C0.ESC + '[1;' + (modifiers + 1) + 'C'; + // HACK: Make Alt + right-arrow behave like Ctrl + right-arrow: move one word forward + // http://unix.stackexchange.com/a/108106 + // macOS uses different escape sequences than linux + if (result.key === C0.ESC + '[1;3C') { + result.key = (this.browser.isMac) ? C0.ESC + 'f' : C0.ESC + '[1;5C'; + } + } else if (this.applicationCursor) { + result.key = C0.ESC + 'OC'; + } else { + result.key = C0.ESC + '[C'; + } + break; + case 38: + // up-arrow + if (modifiers) { + result.key = C0.ESC + '[1;' + (modifiers + 1) + 'A'; + // HACK: Make Alt + up-arrow behave like Ctrl + up-arrow + // http://unix.stackexchange.com/a/108106 + if (result.key === C0.ESC + '[1;3A') { + result.key = C0.ESC + '[1;5A'; + } + } else if (this.applicationCursor) { + result.key = C0.ESC + 'OA'; + } else { + result.key = C0.ESC + '[A'; + } + break; + case 40: + // down-arrow + if (modifiers) { + result.key = C0.ESC + '[1;' + (modifiers + 1) + 'B'; + // HACK: Make Alt + down-arrow behave like Ctrl + down-arrow + // http://unix.stackexchange.com/a/108106 + if (result.key === C0.ESC + '[1;3B') { + result.key = C0.ESC + '[1;5B'; + } + } else if (this.applicationCursor) { + result.key = C0.ESC + 'OB'; + } else { + result.key = C0.ESC + '[B'; + } + break; + case 45: + // insert + if (!ev.shiftKey && !ev.ctrlKey) { + // or + are used to + // copy-paste on some systems. + result.key = C0.ESC + '[2~'; + } + break; + case 46: + // delete + if (modifiers) { + result.key = C0.ESC + '[3;' + (modifiers + 1) + '~'; + } else { + result.key = C0.ESC + '[3~'; + } + break; + case 36: + // home + if (modifiers) + result.key = C0.ESC + '[1;' + (modifiers + 1) + 'H'; + else if (this.applicationCursor) + result.key = C0.ESC + 'OH'; + else + result.key = C0.ESC + '[H'; + break; + case 35: + // end + if (modifiers) + result.key = C0.ESC + '[1;' + (modifiers + 1) + 'F'; + else if (this.applicationCursor) + result.key = C0.ESC + 'OF'; + else + result.key = C0.ESC + '[F'; + break; + case 33: + // page up + if (ev.shiftKey) { + result.scrollLines = -(this.rows - 1); + } else { + result.key = C0.ESC + '[5~'; + } + break; + case 34: + // page down + if (ev.shiftKey) { + result.scrollLines = this.rows - 1; + } else { + result.key = C0.ESC + '[6~'; + } + break; + case 112: + // F1-F12 + if (modifiers) { + result.key = C0.ESC + '[1;' + (modifiers + 1) + 'P'; + } else { + result.key = C0.ESC + 'OP'; + } + break; + case 113: + if (modifiers) { + result.key = C0.ESC + '[1;' + (modifiers + 1) + 'Q'; + } else { + result.key = C0.ESC + 'OQ'; + } + break; + case 114: + if (modifiers) { + result.key = C0.ESC + '[1;' + (modifiers + 1) + 'R'; + } else { + result.key = C0.ESC + 'OR'; + } + break; + case 115: + if (modifiers) { + result.key = C0.ESC + '[1;' + (modifiers + 1) + 'S'; + } else { + result.key = C0.ESC + 'OS'; + } + break; + case 116: + if (modifiers) { + result.key = C0.ESC + '[15;' + (modifiers + 1) + '~'; + } else { + result.key = C0.ESC + '[15~'; + } + break; + case 117: + if (modifiers) { + result.key = C0.ESC + '[17;' + (modifiers + 1) + '~'; + } else { + result.key = C0.ESC + '[17~'; + } + break; + case 118: + if (modifiers) { + result.key = C0.ESC + '[18;' + (modifiers + 1) + '~'; + } else { + result.key = C0.ESC + '[18~'; + } + break; + case 119: + if (modifiers) { + result.key = C0.ESC + '[19;' + (modifiers + 1) + '~'; + } else { + result.key = C0.ESC + '[19~'; + } + break; + case 120: + if (modifiers) { + result.key = C0.ESC + '[20;' + (modifiers + 1) + '~'; + } else { + result.key = C0.ESC + '[20~'; + } + break; + case 121: + if (modifiers) { + result.key = C0.ESC + '[21;' + (modifiers + 1) + '~'; + } else { + result.key = C0.ESC + '[21~'; + } + break; + case 122: + if (modifiers) { + result.key = C0.ESC + '[23;' + (modifiers + 1) + '~'; + } else { + result.key = C0.ESC + '[23~'; + } + break; + case 123: + if (modifiers) { + result.key = C0.ESC + '[24;' + (modifiers + 1) + '~'; + } else { + result.key = C0.ESC + '[24~'; + } + break; + default: + // a-z and space + if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { + if (ev.keyCode >= 65 && ev.keyCode <= 90) { + result.key = String.fromCharCode(ev.keyCode - 64); + } else if (ev.keyCode === 32) { + // NUL + result.key = String.fromCharCode(0); + } else if (ev.keyCode >= 51 && ev.keyCode <= 55) { + // escape, file sep, group sep, record sep, unit sep + result.key = String.fromCharCode(ev.keyCode - 51 + 27); + } else if (ev.keyCode === 56) { + // delete + result.key = String.fromCharCode(127); + } else if (ev.keyCode === 219) { + // ^[ - Control Sequence Introducer (CSI) + result.key = String.fromCharCode(27); + } else if (ev.keyCode === 220) { + // ^\ - String Terminator (ST) + result.key = String.fromCharCode(28); + } else if (ev.keyCode === 221) { + // ^] - Operating System Command (OSC) + result.key = String.fromCharCode(29); + } + } else if (!this.browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) { + // On Mac this is a third level shift. Use instead. + if (ev.keyCode >= 65 && ev.keyCode <= 90) { + result.key = C0.ESC + String.fromCharCode(ev.keyCode + 32); + } else if (ev.keyCode === 192) { + result.key = C0.ESC + '`'; + } else if (ev.keyCode >= 48 && ev.keyCode <= 57) { + result.key = C0.ESC + (ev.keyCode - 48); + } + } else if (this.browser.isMac && !ev.altKey && !ev.ctrlKey && ev.metaKey) { + if (ev.keyCode === 65) { // cmd + a + this.selectAll(); + } + } + break; + } + + return result; + } + + /** + * Set the G level of the terminal + * @param g + */ + public setgLevel(g: number): void { + this.glevel = g; + this.charset = this.charsets[g]; + } + + /** + * Set the charset for the given G level of the terminal + * @param g + * @param charset + */ + public setgCharset(g: number, charset: Charset): void { + this.charsets[g] = charset; + if (this.glevel === g) { + this.charset = charset; + } + } + + /** + * Handle a keypress event. + * Key Resources: + * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent + * @param {KeyboardEvent} ev The keypress event to be handled. + */ + protected _keyPress(ev: KeyboardEvent): boolean { + let key; + + if (this.customKeyEventHandler && this.customKeyEventHandler(ev) === false) { + return false; + } + + this.cancel(ev); + + if (ev.charCode) { + key = ev.charCode; + } else if (ev.which == null) { + key = ev.keyCode; + } else if (ev.which !== 0 && ev.charCode !== 0) { + key = ev.which; + } else { + return false; + } + + if (!key || ( + (ev.altKey || ev.ctrlKey || ev.metaKey) && !isThirdLevelShift(this.browser, ev) + )) { + return false; + } + + key = String.fromCharCode(key); + + this.emit('keypress', key, ev); + this.emit('key', key, ev); + this.showCursor(); + this.handler(key); + + return true; + } + + /** + * Send data for handling to the terminal + * @param {string} data + */ + public send(data: string): void { + if (!this.sendDataQueue) { + setTimeout(() => { + this.handler(this.sendDataQueue); + this.sendDataQueue = ''; + }, 1); + } + + this.sendDataQueue += data; + } + + /** + * Ring the bell. + * Note: We could do sweet things with webaudio here + */ + public bell(): void { + this.emit('bell'); + if (this.soundBell()) this.bellAudioElement.play(); + + if (this.visualBell()) { + this.element.classList.add('visual-bell-active'); + clearTimeout(this.visualBellTimer); + this.visualBellTimer = window.setTimeout(() => { + this.element.classList.remove('visual-bell-active'); + }, 200); + } + } + + /** + * Log the current state to the console. + */ + public log(text: string, data?: any): void { + if (!this.options.debug) return; + if (!this.context.console || !this.context.console.log) return; + this.context.console.log(text, data); + } + + /** + * Log the current state as error to the console. + */ + public error(text: string, data?: any): void { + if (!this.options.debug) return; + if (!this.context.console || !this.context.console.error) return; + this.context.console.error(text, data); + } + + /** + * Resizes the terminal. + * + * @param {number} x The number of columns to resize to. + * @param {number} y The number of rows to resize to. + */ + public resize(x: number, y: number): void { + if (isNaN(x) || isNaN(y)) { + return; + } + + if (x === this.cols && y === this.rows) { + // Check if we still need to measure the char size (fixes #785). + if (!this.charMeasure.width || !this.charMeasure.height) { + this.charMeasure.measure(this.options); + } + return; + } + + if (x < 1) x = 1; + if (y < 1) y = 1; + + this.buffers.resize(x, y); + + this.cols = x; + this.rows = y; + this.buffers.setupTabStops(this.cols); + + this.charMeasure.measure(this.options); + + this.refresh(0, this.rows - 1); + this.emit('resize', {cols: x, rows: y}); + } + + /** + * Updates the range of rows to refresh + * @param {number} y The number of rows to refresh next. + */ + public updateRange(y: number): void { + if (y < this.refreshStart) this.refreshStart = y; + if (y > this.refreshEnd) this.refreshEnd = y; + // if (y > this.refreshEnd) { + // this.refreshEnd = y; + // if (y > this.rows - 1) { + // this.refreshEnd = this.rows - 1; + // } + // } + } + + /** + * Set the range of refreshing to the maximum value + */ + public maxRange(): void { + this.refreshStart = 0; + this.refreshEnd = this.rows - 1; + } + + /** + * Erase in the identified line everything from "x" to the end of the line (right). + * @param {number} x The column from which to start erasing to the end of the line. + * @param {number} y The line in which to operate. + */ + public eraseRight(x: number, y: number): void { + const line = this.buffer.lines.get(this.buffer.ybase + y); + if (!line) { + return; + } + const ch: CharData = [this.eraseAttr(), ' ', 1, 32 /* ' '.charCodeAt(0) */]; // xterm + for (; x < this.cols; x++) { + line[x] = ch; + } + this.updateRange(y); + } + + /** + * Erase in the identified line everything from "x" to the start of the line (left). + * @param {number} x The column from which to start erasing to the start of the line. + * @param {number} y The line in which to operate. + */ + public eraseLeft(x: number, y: number): void { + const line = this.buffer.lines.get(this.buffer.ybase + y); + if (!line) { + return; + } + const ch: CharData = [this.eraseAttr(), ' ', 1, 32 /* ' '.charCodeAt(0) */]; // xterm + x++; + while (x--) { + line[x] = ch; + } + this.updateRange(y); + } + + /** + * Clear the entire buffer, making the prompt line the new first line. + */ + public clear(): void { + if (this.buffer.ybase === 0 && this.buffer.y === 0) { + // Don't clear if it's already clear + return; + } + this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y)); + this.buffer.lines.length = 1; + this.buffer.ydisp = 0; + this.buffer.ybase = 0; + this.buffer.y = 0; + for (let i = 1; i < this.rows; i++) { + this.buffer.lines.push(this.blankLine()); + } + this.refresh(0, this.rows - 1); + this.emit('scroll', this.buffer.ydisp); + } + + /** + * Erase all content in the given line + * @param {number} y The line to erase all of its contents. + */ + public eraseLine(y: number): void { + this.eraseRight(0, y); + } + + /** + * Return the data array of a blank line + * @param {boolean} cur First bunch of data for each "blank" character. + * @param {boolean} isWrapped Whether the new line is wrapped from the previous line. + * @param {boolean} cols The number of columns in the terminal, if this is not + * set, the terminal's current column count would be used. + */ + public blankLine(cur?: boolean, isWrapped?: boolean, cols?: number): LineData { + const attr = cur ? this.eraseAttr() : this.defAttr; + + const ch: CharData = [attr, ' ', 1, 32 /* ' '.charCodeAt(0) */]; // width defaults to 1 halfwidth character + const line: LineData = []; + + // TODO: It is not ideal that this is a property on an array, a buffer line + // class should be added that will hold this data and other useful functions. + if (isWrapped) { + (line).isWrapped = isWrapped; + } + + cols = cols || this.cols; + for (let i = 0; i < cols; i++) { + line[i] = ch; + } + + return line; + } + + /** + * If cur return the back color xterm feature attribute. Else return defAttr. + * @param cur + */ + public ch(cur?: boolean): CharData { + if (cur) { + return [this.eraseAttr(), ' ', 1, 32 /* ' '.charCodeAt(0) */]; + } + return [this.defAttr, ' ', 1, 32 /* ' '.charCodeAt(0) */]; + } + + /** + * Evaluate if the current terminal is the given argument. + * @param term The terminal name to evaluate + */ + public is(term: string): boolean { + return (this.options.termName + '').indexOf(term) === 0; + } + + /** + * Emit the 'data' event and populate the given data. + * @param {string} data The data to populate in the event. + */ + public handler(data: string): void { + // Prevents all events to pty process if stdin is disabled + if (this.options.disableStdin) { + return; + } + + // Clear the selection if the selection manager is available and has an active selection + if (this.selectionManager && this.selectionManager.hasSelection) { + this.selectionManager.clearSelection(); + } + + // Input is being sent to the terminal, the terminal should focus the prompt. + if (this.buffer.ybase !== this.buffer.ydisp) { + this.scrollToBottom(); + } + this.emit('data', data); + } + + /** + * Emit the 'title' event and populate the given title. + * @param {string} title The title to populate in the event. + */ + private handleTitle(title: string): void { + /** + * This event is emitted when the title of the terminal is changed + * from inside the terminal. The parameter is the new title. + * + * @event title + */ + this.emit('title', title); + } + + /** + * ESC + */ + + /** + * ESC D Index (IND is 0x84). + */ + public index(): void { + this.buffer.y++; + if (this.buffer.y > this.buffer.scrollBottom) { + this.buffer.y--; + this.scroll(); + } + // If the end of the line is hit, prevent this action from wrapping around to the next line. + if (this.buffer.x >= this.cols) { + this.buffer.x--; + } + } + + /** + * ESC M Reverse Index (RI is 0x8d). + * + * Move the cursor up one row, inserting a new blank line if necessary. + */ + public reverseIndex(): void { + if (this.buffer.y === this.buffer.scrollTop) { + // possibly move the code below to term.reverseScroll(); + // test: echo -ne '\e[1;1H\e[44m\eM\e[0m' + // blankLine(true) is xterm/linux behavior + const scrollRegionHeight = this.buffer.scrollBottom - this.buffer.scrollTop; + this.buffer.lines.shiftElements(this.buffer.y + this.buffer.ybase, scrollRegionHeight, 1); + this.buffer.lines.set(this.buffer.y + this.buffer.ybase, this.blankLine(true)); + this.updateRange(this.buffer.scrollTop); + this.updateRange(this.buffer.scrollBottom); + } else { + this.buffer.y--; + } + } + + /** + * ESC c Full Reset (RIS). + */ + public reset(): void { + this.options.rows = this.rows; + this.options.cols = this.cols; + const customKeyEventHandler = this.customKeyEventHandler; + const inputHandler = this.inputHandler; + const buffers = this.buffers; + this.setup(); + this.customKeyEventHandler = customKeyEventHandler; + this.inputHandler = inputHandler; + this.buffers = buffers; + this.refresh(0, this.rows - 1); + this.viewport.syncScrollArea(); + } + + + /** + * ESC H Tab Set (HTS is 0x88). + */ + private tabSet(): void { + this.buffer.tabs[this.buffer.x] = true; + } + + // TODO: Remove cancel function and cancelEvents option + public cancel(ev: Event, force?: boolean): boolean { + if (!this.options.cancelEvents && !force) { + return; + } + ev.preventDefault(); + ev.stopPropagation(); + return false; + } + + // TODO: Remove when true color is implemented + public matchColor(r1: number, g1: number, b1: number): number { + return matchColor_(r1, g1, b1); + } + + private visualBell(): boolean { + return this.options.bellStyle === 'visual' || + this.options.bellStyle === 'both'; + } + + private soundBell(): boolean { + return this.options.bellStyle === 'sound' || + this.options.bellStyle === 'both'; + } + + private syncBellSound(): void { + // Don't update anything if the terminal has not been opened yet + if (!this.element) { + return; + } + + if (this.soundBell() && this.bellAudioElement) { + this.bellAudioElement.setAttribute('src', this.options.bellSound); + } else if (this.soundBell()) { + this.bellAudioElement = document.createElement('audio'); + this.bellAudioElement.setAttribute('preload', 'auto'); + this.bellAudioElement.setAttribute('src', this.options.bellSound); + this.helperContainer.appendChild(this.bellAudioElement); + } else if (this.bellAudioElement) { + this.helperContainer.removeChild(this.bellAudioElement); + } + } +} + +/** + * Helpers + */ + +function globalOn(el: any, type: string, handler: (event: Event) => any, capture?: boolean): void { + if (!Array.isArray(el)) { + el = [el]; + } + el.forEach((element: HTMLElement) => { + element.addEventListener(type, handler, capture || false); + }); +} +// TODO: Remove once everything is typed +const on = globalOn; + +function off(el: any, type: string, handler: (event: Event) => any, capture: boolean = false): void { + el.removeEventListener(type, handler, capture); +} + +function isThirdLevelShift(browser: IBrowser, ev: KeyboardEvent): boolean { + const thirdLevelKey = + (browser.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) || + (browser.isMSWindows && ev.altKey && ev.ctrlKey && !ev.metaKey); + + if (ev.type === 'keypress') { + return thirdLevelKey; + } + + // Don't invoke for arrows, pageDown, home, backspace, etc. (on non-keypress events) + return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47); +} + +function wasMondifierKeyOnlyEvent(ev: KeyboardEvent): boolean { + return ev.keyCode === 16 || // Shift + ev.keyCode === 17 || // Ctrl + ev.keyCode === 18; // Alt +} + +/** + * TODO: + * The below color-related code can be removed when true color is implemented. + * It's only purpose is to match true color requests with the closest matching + * ANSI color code. + */ + +// Colors 0-15 + 16-255 +// Much thanks to TooTallNate for writing this. +const vcolors: number[][] = (function(): number[][] { + const result = DEFAULT_ANSI_COLORS.map(c => { + c = c.substring(1); + return [ + parseInt(c.substring(0, 2), 16), + parseInt(c.substring(2, 4), 16), + parseInt(c.substring(4, 6), 16) + ]; + }); + const r = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]; + + // 16-231 + for (let i = 0; i < 216; i++) { + result.push([ + r[(i / 36) % 6 | 0], + r[(i / 6) % 6 | 0], + r[i % 6] + ]); + } + + // 232-255 (grey) + let c: number; + for (let i = 0; i < 24; i++) { + c = 8 + i * 10; + result.push([c, c, c]); + } + + return result; +})(); + +const matchColorCache: {[colorRGBHash: number]: number} = {}; + +// http://stackoverflow.com/questions/1633828 +function matchColorDistance(r1: number, g1: number, b1: number, r2: number, g2: number, b2: number): number { + return Math.pow(30 * (r1 - r2), 2) + + Math.pow(59 * (g1 - g2), 2) + + Math.pow(11 * (b1 - b2), 2); +}; + + +function matchColor_(r1: number, g1: number, b1: number): number { + const hash = (r1 << 16) | (g1 << 8) | b1; + + if (matchColorCache[hash] != null) { + return matchColorCache[hash]; + } + + let ldiff = Infinity; + let li = -1; + let i = 0; + let c: number[]; + let r2: number; + let g2: number; + let b2: number; + let diff: number; + + for (; i < vcolors.length; i++) { + c = vcolors[i]; + r2 = c[0]; + g2 = c[1]; + b2 = c[2]; + + diff = matchColorDistance(r1, g1, b1, r2, g2, b2); + + if (diff === 0) { + li = i; + break; + } + + if (diff < ldiff) { + ldiff = diff; + li = i; + } + } + + return matchColorCache[hash] = li; +} diff --git a/xterm.js/src/Types.ts b/xterm.js/src/Types.ts new file mode 100644 index 0000000..a0c03fd --- /dev/null +++ b/xterm.js/src/Types.ts @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +export type LinkMatcher = { + id: number, + regex: RegExp, + handler: LinkMatcherHandler, + hoverTooltipCallback?: LinkMatcherHandler, + hoverLeaveCallback?: () => void, + matchIndex?: number, + validationCallback?: LinkMatcherValidationCallback, + priority?: number +}; +export type LinkMatcherHandler = (event: MouseEvent, uri: string) => boolean | void; +export type LinkMatcherValidationCallback = (uri: string, callback: (isValid: boolean) => void) => void; + +export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean; +export type Charset = {[key: string]: string}; + +export type CharData = [number, string, number, number]; +export type LineData = CharData[]; + +export type LinkHoverEvent = { + x: number, + y: number, + length: number +}; + +export enum LinkHoverEventTypes { + HOVER = 'linkhover', + TOOLTIP = 'linktooltip', + LEAVE = 'linkleave' +}; diff --git a/xterm.js/src/Viewport.ts b/xterm.js/src/Viewport.ts new file mode 100644 index 0000000..1ea7fa0 --- /dev/null +++ b/xterm.js/src/Viewport.ts @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ITerminal, IViewport } from './Interfaces'; +import { CharMeasure } from './utils/CharMeasure'; +import { IColorSet } from './renderer/Interfaces'; + +/** + * Represents the viewport of a terminal, the visible area within the larger buffer of output. + * Logic for the virtual scroll bar is included in this object. + */ +export class Viewport implements IViewport { + private currentRowHeight: number = 0; + private lastRecordedBufferLength: number = 0; + private lastRecordedViewportHeight: number = 0; + private lastRecordedBufferHeight: number = 0; + private lastTouchY: number; + + /** + * Creates a new Viewport. + * @param terminal The terminal this viewport belongs to. + * @param viewportElement The DOM element acting as the viewport. + * @param scrollArea The DOM element acting as the scroll area. + * @param charMeasure A DOM element used to measure the character size of. the terminal. + */ + constructor( + private terminal: ITerminal, + private viewportElement: HTMLElement, + private scrollArea: HTMLElement, + private charMeasure: CharMeasure + ) { + this.viewportElement.addEventListener('scroll', this.onScroll.bind(this)); + + // Perform this async to ensure the CharMeasure is ready. + setTimeout(() => this.syncScrollArea(), 0); + } + + public onThemeChanged(colors: IColorSet): void { + this.viewportElement.style.backgroundColor = colors.background; + } + + /** + * Refreshes row height, setting line-height, viewport height and scroll area height if + * necessary. + */ + private refresh(): void { + if (this.charMeasure.height > 0) { + this.currentRowHeight = this.terminal.renderer.dimensions.scaledCellHeight / window.devicePixelRatio; + + if (this.lastRecordedViewportHeight !== this.terminal.renderer.dimensions.canvasHeight) { + this.lastRecordedViewportHeight = this.terminal.renderer.dimensions.canvasHeight; + this.viewportElement.style.height = this.lastRecordedViewportHeight + 'px'; + } + + const newBufferHeight = Math.round(this.currentRowHeight * this.lastRecordedBufferLength); + if (this.lastRecordedBufferHeight !== newBufferHeight) { + this.lastRecordedBufferHeight = newBufferHeight; + this.scrollArea.style.height = this.lastRecordedBufferHeight + 'px'; + } + } + } + + /** + * Updates dimensions and synchronizes the scroll area if necessary. + */ + public syncScrollArea(): void { + if (this.lastRecordedBufferLength !== this.terminal.buffer.lines.length) { + // If buffer height changed + this.lastRecordedBufferLength = this.terminal.buffer.lines.length; + this.refresh(); + } else if (this.lastRecordedViewportHeight !== (this.terminal).renderer.dimensions.canvasHeight) { + // If viewport height changed + this.refresh(); + } else { + // If size has changed, refresh viewport + if (this.terminal.renderer.dimensions.scaledCellHeight / window.devicePixelRatio !== this.currentRowHeight) { + this.refresh(); + } + } + + // Sync scrollTop + const scrollTop = this.terminal.buffer.ydisp * this.currentRowHeight; + if (this.viewportElement.scrollTop !== scrollTop) { + this.viewportElement.scrollTop = scrollTop; + } + } + + /** + * Handles scroll events on the viewport, calculating the new viewport and requesting the + * terminal to scroll to it. + * @param ev The scroll event. + */ + private onScroll(ev: Event): void { + const newRow = Math.round(this.viewportElement.scrollTop / this.currentRowHeight); + const diff = newRow - this.terminal.buffer.ydisp; + this.terminal.scrollLines(diff, true); + } + + /** + * Handles mouse wheel events by adjusting the viewport's scrollTop and delegating the actual + * scrolling to `onScroll`, this event needs to be attached manually by the consumer of + * `Viewport`. + * @param ev The mouse wheel event. + */ + public onWheel(ev: WheelEvent): void { + if (ev.deltaY === 0) { + // Do nothing if it's not a vertical scroll event + return; + } + // Fallback to WheelEvent.DOM_DELTA_PIXEL + let multiplier = 1; + if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) { + multiplier = this.currentRowHeight; + } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) { + multiplier = this.currentRowHeight * this.terminal.rows; + } + this.viewportElement.scrollTop += ev.deltaY * multiplier; + // Prevent the page from scrolling when the terminal scrolls + ev.preventDefault(); + }; + + /** + * Handles the touchstart event, recording the touch occurred. + * @param ev The touch event. + */ + public onTouchStart(ev: TouchEvent): void { + this.lastTouchY = ev.touches[0].pageY; + }; + + /** + * Handles the touchmove event, scrolling the viewport if the position shifted. + * @param ev The touch event. + */ + public onTouchMove(ev: TouchEvent): void { + let deltaY = this.lastTouchY - ev.touches[0].pageY; + this.lastTouchY = ev.touches[0].pageY; + if (deltaY === 0) { + return; + } + this.viewportElement.scrollTop += deltaY; + ev.preventDefault(); + }; +} diff --git a/xterm.js/src/addons/attach/attach.test.ts b/xterm.js/src/addons/attach/attach.test.ts new file mode 100644 index 0000000..9bf0e07 --- /dev/null +++ b/xterm.js/src/addons/attach/attach.test.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert, expect } from 'chai'; + +import * as attach from './attach' + +class MockTerminal {} + +describe('attach addon', () => { + describe('apply', () => { + it('should do register the `attach` and `detach` methods', () => { + attach.apply(MockTerminal); + assert.equal(typeof (MockTerminal).prototype.attach, 'function'); + assert.equal(typeof (MockTerminal).prototype.detach, 'function'); + }); + }); +}); diff --git a/xterm.js/src/addons/attach/attach.ts b/xterm.js/src/addons/attach/attach.ts new file mode 100644 index 0000000..4e0d594 --- /dev/null +++ b/xterm.js/src/addons/attach/attach.ts @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * @license MIT + * + * Implements the attach method, that attaches the terminal to a WebSocket stream. + */ + +/** + * Attaches the given terminal to the given socket. + * + * @param {Terminal} term - The terminal to be attached to the given socket. + * @param {WebSocket} socket - The socket to attach the current terminal. + * @param {boolean} bidirectional - Whether the terminal should send data + * to the socket as well. + * @param {boolean} buffered - Whether the rendering of incoming data + * should happen instantly or at a maximum + * frequency of 1 rendering per 10ms. + */ +export function attach(term, socket, bidirectional, buffered) { + bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; + term.socket = socket; + + term._flushBuffer = function() { + term.write(term._attachSocketBuffer); + term._attachSocketBuffer = null; + }; + + term._pushToBuffer = function(data) { + if (term._attachSocketBuffer) { + term._attachSocketBuffer += data; + } else { + term._attachSocketBuffer = data; + setTimeout(term._flushBuffer, 10); + } + }; + + var myTextDecoder; + + term._getMessage = function(ev) { + var str; + if (typeof ev.data === "object") { + if (ev.data instanceof ArrayBuffer) { + if (!myTextDecoder) { + myTextDecoder = new TextDecoder(); + } + + str = myTextDecoder.decode( ev.data ); + } + else { + throw "TODO: handle Blob?"; + } + } + + if (buffered) { + term._pushToBuffer(str || ev.data); + } else { + term.write(str || ev.data); + } + }; + + term._sendData = function(data) { + if (socket.readyState !== 1) { + return; + } + socket.send(data); + }; + + socket.addEventListener('message', term._getMessage); + + if (bidirectional) { + term.on('data', term._sendData); + } + + socket.addEventListener('close', term.detach.bind(term, socket)); + socket.addEventListener('error', term.detach.bind(term, socket)); +}; + +/** + * Detaches the given terminal from the given socket + * + * @param {Terminal} term - The terminal to be detached from the given socket. + * @param {WebSocket} socket - The socket from which to detach the current + * terminal. + */ +export function detach(term, socket) { + term.off('data', term._sendData); + + socket = (typeof socket == 'undefined') ? term.socket : socket; + + if (socket) { + socket.removeEventListener('message', term._getMessage); + } + + delete term.socket; +}; + + +export function apply(terminalConstructor) { + /** + * Attaches the current terminal to the given socket + * + * @param {WebSocket} socket - The socket to attach the current terminal. + * @param {boolean} bidirectional - Whether the terminal should send data + * to the socket as well. + * @param {boolean} buffered - Whether the rendering of incoming data + * should happen instantly or at a maximum + * frequency of 1 rendering per 10ms. + */ + terminalConstructor.prototype.attach = function(socket, bidirectional, buffered) { + return attach(this, socket, bidirectional, buffered); + }; + + /** + * Detaches the current terminal from the given socket. + * + * @param {WebSocket} socket - The socket from which to detach the current + * terminal. + */ + terminalConstructor.prototype.detach = function(socket) { + return detach(this, socket); + }; +} diff --git a/xterm.js/src/addons/attach/index.html b/xterm.js/src/addons/attach/index.html new file mode 100644 index 0000000..b6f853b --- /dev/null +++ b/xterm.js/src/addons/attach/index.html @@ -0,0 +1,93 @@ + + + + + + + + + + +
+ +

+ xterm.js: socket attach +

+

+ Attach the terminal to a WebSocket terminal stream with ease. Perfect for attaching to your + Docker containers. +

+

+ Socket information +

+
+ + +
+
+ +
+ + + \ No newline at end of file diff --git a/xterm.js/src/addons/attach/package.json b/xterm.js/src/addons/attach/package.json new file mode 100644 index 0000000..9e45068 --- /dev/null +++ b/xterm.js/src/addons/attach/package.json @@ -0,0 +1,5 @@ +{ + "name": "xterm.attach", + "main": "attach.js", + "private": true +} diff --git a/xterm.js/src/addons/attach/tsconfig.json b/xterm.js/src/addons/attach/tsconfig.json new file mode 100644 index 0000000..9772232 --- /dev/null +++ b/xterm.js/src/addons/attach/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "rootDir": ".", + "outDir": "../../../lib/addons/attach/", + "sourceMap": true, + "removeComments": true + } +} diff --git a/xterm.js/src/addons/fit/fit.test.ts b/xterm.js/src/addons/fit/fit.test.ts new file mode 100644 index 0000000..159cc98 --- /dev/null +++ b/xterm.js/src/addons/fit/fit.test.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert, expect } from 'chai'; + +import * as fit from './fit' + +class MockTerminal {} + +describe('fit addon', () => { + describe('apply', () => { + it('should do register the `proposeGeometry` and `fit` methods', () => { + fit.apply(MockTerminal); + assert.equal(typeof (MockTerminal).prototype.proposeGeometry, 'function'); + assert.equal(typeof (MockTerminal).prototype.fit, 'function'); + }); + }); +}); diff --git a/xterm.js/src/addons/fit/fit.ts b/xterm.js/src/addons/fit/fit.ts new file mode 100644 index 0000000..b87ccc0 --- /dev/null +++ b/xterm.js/src/addons/fit/fit.ts @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * @license MIT + * + * Fit terminal columns and rows to the dimensions of its DOM element. + * + * ## Approach + * + * Rows: Truncate the division of the terminal parent element height by the + * terminal row height. + * Columns: Truncate the division of the terminal parent element width by the + * terminal character width (apply display: inline at the terminal + * row and truncate its width with the current number of columns). + */ + +export function proposeGeometry(term) { + if (!term.element.parentElement) { + return null; + } + var parentElementStyle = window.getComputedStyle(term.element.parentElement); + var parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')); + var parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17); + var elementStyle = window.getComputedStyle(term.element); + var elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')); + var elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')); + var availableHeight = parentElementHeight - elementPaddingVer; + var availableWidth = parentElementWidth - elementPaddingHor; + var geometry = { + cols: Math.floor(availableWidth / term.renderer.dimensions.actualCellWidth), + rows: Math.floor(availableHeight / term.renderer.dimensions.actualCellHeight) + }; + + return geometry; +}; + +export function fit(term) { + var geometry = proposeGeometry(term); + if (geometry) { + // Force a full render + if (term.rows !== geometry.rows || term.cols !== geometry.cols) { + term.renderer.clear(); + term.resize(geometry.cols, geometry.rows); + } + } +}; + +export function apply(terminalConstructor) { + terminalConstructor.prototype.proposeGeometry = function() { + return proposeGeometry(this); + } + + terminalConstructor.prototype.fit = function() { + return fit(this); + } +} diff --git a/xterm.js/src/addons/fit/package.json b/xterm.js/src/addons/fit/package.json new file mode 100644 index 0000000..f7cb5bc --- /dev/null +++ b/xterm.js/src/addons/fit/package.json @@ -0,0 +1,5 @@ +{ + "name": "xterm.fit", + "main": "fit.js", + "private": true +} diff --git a/xterm.js/src/addons/fit/tsconfig.json b/xterm.js/src/addons/fit/tsconfig.json new file mode 100644 index 0000000..949f8b6 --- /dev/null +++ b/xterm.js/src/addons/fit/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "rootDir": ".", + "outDir": "../../../lib/addons/fit/", + "sourceMap": true, + "removeComments": true + } +} diff --git a/xterm.js/src/addons/fullscreen/fullscreen.css b/xterm.js/src/addons/fullscreen/fullscreen.css new file mode 100644 index 0000000..60e8c51 --- /dev/null +++ b/xterm.js/src/addons/fullscreen/fullscreen.css @@ -0,0 +1,10 @@ +.xterm.fullscreen { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: auto; + height: auto; + z-index: 255; +} diff --git a/xterm.js/src/addons/fullscreen/fullscreen.test.ts b/xterm.js/src/addons/fullscreen/fullscreen.test.ts new file mode 100644 index 0000000..c77ea75 --- /dev/null +++ b/xterm.js/src/addons/fullscreen/fullscreen.test.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert, expect } from 'chai'; + +import * as fullscreen from './fullscreen' + +class MockTerminal {} + +describe('fullscreen addon', () => { + describe('apply', () => { + it('should do register the `toggleFullscreen` method', () => { + fullscreen.apply(MockTerminal); + assert.equal(typeof (MockTerminal).prototype.toggleFullScreen, 'function'); + }); + }); +}); diff --git a/xterm.js/src/addons/fullscreen/fullscreen.ts b/xterm.js/src/addons/fullscreen/fullscreen.ts new file mode 100644 index 0000000..31ab518 --- /dev/null +++ b/xterm.js/src/addons/fullscreen/fullscreen.ts @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * @license MIT + */ + +/** + * Toggle the given terminal's fullscreen mode. + * @param {Terminal} term - The terminal to toggle full screen mode + * @param {boolean} fullscreen - Toggle fullscreen on (true) or off (false) + */ +export function toggleFullScreen(term, fullscreen) { + var fn; + + if (typeof fullscreen == 'undefined') { + fn = (term.element.classList.contains('fullscreen')) ? 'remove' : 'add'; + } else if (!fullscreen) { + fn = 'remove'; + } else { + fn = 'add'; + } + + term.element.classList[fn]('fullscreen'); +}; + +export function apply(terminalConstructor) { + terminalConstructor.prototype.toggleFullScreen = function (fullscreen) { + return toggleFullScreen(this, fullscreen); + }; +} diff --git a/xterm.js/src/addons/fullscreen/package.json b/xterm.js/src/addons/fullscreen/package.json new file mode 100644 index 0000000..fdaf688 --- /dev/null +++ b/xterm.js/src/addons/fullscreen/package.json @@ -0,0 +1,5 @@ +{ + "name": "xterm.fullscreen", + "main": "fullscreen.js", + "private": true +} diff --git a/xterm.js/src/addons/fullscreen/tsconfig.json b/xterm.js/src/addons/fullscreen/tsconfig.json new file mode 100644 index 0000000..b04144c --- /dev/null +++ b/xterm.js/src/addons/fullscreen/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "rootDir": ".", + "outDir": "../../../lib/addons/fullscreen/", + "sourceMap": true, + "removeComments": true + } +} diff --git a/xterm.js/src/addons/search/SearchHelper.ts b/xterm.js/src/addons/search/SearchHelper.ts new file mode 100644 index 0000000..5735dd4 --- /dev/null +++ b/xterm.js/src/addons/search/SearchHelper.ts @@ -0,0 +1,140 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +// import { ITerminal } from '../../Interfaces'; +// import { translateBufferLineToString } from '../../utils/BufferLine'; + +interface ISearchResult { + term: string; + col: number; + row: number; +} + +/** + * A class that knows how to search the terminal and how to display the results. + */ +export class SearchHelper { + constructor(private _terminal: any) { + // TODO: Search for multiple instances on 1 line + // TODO: Don't use the actual selection, instead use a "find selection" so multiple instances can be highlighted + // TODO: Highlight other instances in the viewport + // TODO: Support regex, case sensitivity, etc. + } + + /** + * Find the next instance of the term, then scroll to and select it. If it + * doesn't exist, do nothing. + * @param term Tne search term. + * @return Whether a result was found. + */ + public findNext(term: string): boolean { + if (!term || term.length === 0) { + return false; + } + + let result: ISearchResult; + + let startRow = this._terminal.buffer.ydisp; + if (this._terminal.selectionManager.selectionEnd) { + // Start from the selection end if there is a selection + startRow = this._terminal.selectionManager.selectionEnd[1]; + } + + // Search from ydisp + 1 to end + for (let y = startRow + 1; y < this._terminal.buffer.ybase + this._terminal.rows; y++) { + result = this._findInLine(term, y); + if (result) { + break; + } + } + + // Search from the top to the current ydisp + if (!result) { + for (let y = 0; y < startRow; y++) { + result = this._findInLine(term, y); + if (result) { + break; + } + } + } + + // Set selection and scroll if a result was found + return this._selectResult(result); + } + + /** + * Find the previous instance of the term, then scroll to and select it. If it + * doesn't exist, do nothing. + * @param term Tne search term. + * @return Whether a result was found. + */ + public findPrevious(term: string): boolean { + if (!term || term.length === 0) { + return false; + } + + let result: ISearchResult; + + let startRow = this._terminal.buffer.ydisp; + if (this._terminal.selectionManager.selectionStart) { + // Start from the selection end if there is a selection + startRow = this._terminal.selectionManager.selectionStart[1]; + } + + // Search from ydisp + 1 to end + for (let y = startRow - 1; y >= 0; y--) { + result = this._findInLine(term, y); + if (result) { + break; + } + } + + // Search from the top to the current ydisp + if (!result) { + for (let y = this._terminal.buffer.ybase + this._terminal.rows - 1; y > startRow; y--) { + result = this._findInLine(term, y); + if (result) { + break; + } + } + } + + // Set selection and scroll if a result was found + return this._selectResult(result); + } + + /** + * Searches a line for a search term. + * @param term Tne search term. + * @param y The line to search. + * @return The search result if it was found. + */ + private _findInLine(term: string, y: number): ISearchResult { + const lowerStringLine = this._terminal.buffer.translateBufferLineToString(y, true).toLowerCase(); + const lowerTerm = term.toLowerCase(); + const searchIndex = lowerStringLine.indexOf(lowerTerm); + if (searchIndex >= 0) { + return { + term, + col: searchIndex, + row: y + }; + } + } + + /** + * Selects and scrolls to a result. + * @param result The result to select. + * @return Whethera result was selected. + */ + private _selectResult(result: ISearchResult): boolean { + if (!result) { + return false; + } + this._terminal.selectionManager.setSelection(result.col, result.row, result.term.length); + this._terminal.scrollLines(result.row - this._terminal.buffer.ydisp, false); + return true; + } +} diff --git a/xterm.js/src/addons/search/package.json b/xterm.js/src/addons/search/package.json new file mode 100644 index 0000000..552e933 --- /dev/null +++ b/xterm.js/src/addons/search/package.json @@ -0,0 +1,5 @@ +{ + "name": "xterm.search", + "main": "search.js", + "private": true +} diff --git a/xterm.js/src/addons/search/search.ts b/xterm.js/src/addons/search/search.ts new file mode 100644 index 0000000..480fea7 --- /dev/null +++ b/xterm.js/src/addons/search/search.ts @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { SearchHelper } from './SearchHelper'; + + +/** + * Find the next instance of the term, then scroll to and select it. If it + * doesn't exist, do nothing. + * @param term Tne search term. + * @return Whether a result was found. + */ +export function findNext(terminal: any, term: string): boolean { + if (!terminal._searchHelper) { + terminal.searchHelper = new SearchHelper(terminal); + } + return (terminal.searchHelper).findNext(term); +}; + +/** + * Find the previous instance of the term, then scroll to and select it. If it + * doesn't exist, do nothing. + * @param term Tne search term. + * @return Whether a result was found. + */ +export function findPrevious(terminal: any, term: string): boolean { + if (!terminal._searchHelper) { + terminal.searchHelper = new SearchHelper(terminal); + } + return (terminal.searchHelper).findPrevious(term); +}; + +export function apply(terminalConstructor) { + terminalConstructor.prototype.findNext = function(term) { + return findNext(this, term); + } + + terminalConstructor.prototype.findPrevious = function(term) { + return findPrevious(this, term); + } +} diff --git a/xterm.js/src/addons/search/tsconfig.json b/xterm.js/src/addons/search/tsconfig.json new file mode 100644 index 0000000..7f72e47 --- /dev/null +++ b/xterm.js/src/addons/search/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "rootDir": ".", + "outDir": "../../../lib/addons/search/", + "sourceMap": true, + "removeComments": true + } +} diff --git a/xterm.js/src/addons/terminado/package.json b/xterm.js/src/addons/terminado/package.json new file mode 100644 index 0000000..d695959 --- /dev/null +++ b/xterm.js/src/addons/terminado/package.json @@ -0,0 +1,5 @@ +{ + "name": "xterm.terminado", + "main": "terminado.js", + "private": true +} diff --git a/xterm.js/src/addons/terminado/terminado.test.ts b/xterm.js/src/addons/terminado/terminado.test.ts new file mode 100644 index 0000000..fe05989 --- /dev/null +++ b/xterm.js/src/addons/terminado/terminado.test.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert, expect } from 'chai'; + +import * as terminado from './terminado' + +class MockTerminal {} + +describe('terminado addon', () => { + describe('apply', () => { + it('should do register the `terminadoAttach` and `terminadoDetach` methods', () => { + terminado.apply(MockTerminal); + assert.equal(typeof (MockTerminal).prototype.terminadoAttach, 'function'); + assert.equal(typeof (MockTerminal).prototype.terminadoDetach, 'function'); + }); + }); +}); diff --git a/xterm.js/src/addons/terminado/terminado.ts b/xterm.js/src/addons/terminado/terminado.ts new file mode 100644 index 0000000..9a7c7ad --- /dev/null +++ b/xterm.js/src/addons/terminado/terminado.ts @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + * + * This module provides methods for attaching a terminal to a terminado + * WebSocket stream. + */ + +/** + * Attaches the given terminal to the given socket. + * + * @param {Terminal} term - The terminal to be attached to the given socket. + * @param {WebSocket} socket - The socket to attach the current terminal. + * @param {boolean} bidirectional - Whether the terminal should send data + * to the socket as well. + * @param {boolean} buffered - Whether the rendering of incoming data + * should happen instantly or at a maximum + * frequency of 1 rendering per 10ms. + */ +export function terminadoAttach(term, socket, bidirectional, buffered) { + bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; + term.socket = socket; + + term._flushBuffer = function() { + term.write(term._attachSocketBuffer); + term._attachSocketBuffer = null; + }; + + term._pushToBuffer = function(data) { + if (term._attachSocketBuffer) { + term._attachSocketBuffer += data; + } else { + term._attachSocketBuffer = data; + setTimeout(term._flushBuffer, 10); + } + }; + + term._getMessage = function(ev) { + var data = JSON.parse(ev.data) + if( data[0] == "stdout" ) { + if (buffered) { + term._pushToBuffer(data[1]); + } else { + term.write(data[1]); + } + } + }; + + term._sendData = function(data) { + socket.send(JSON.stringify(['stdin', data])); + }; + + term._setSize = function(size) { + socket.send(JSON.stringify(['set_size', size.rows, size.cols])); + }; + + socket.addEventListener('message', term._getMessage); + + if (bidirectional) { + term.on('data', term._sendData); + } + term.on('resize', term._setSize); + + socket.addEventListener('close', term.terminadoDetach.bind(term, socket)); + socket.addEventListener('error', term.terminadoDetach.bind(term, socket)); +}; + +/** + * Detaches the given terminal from the given socket + * + * @param {Xterm} term - The terminal to be detached from the given socket. + * @param {WebSocket} socket - The socket from which to detach the current + * terminal. + */ +export function terminadoDetach(term, socket) { + term.off('data', term._sendData); + + socket = (typeof socket == 'undefined') ? term.socket : socket; + + if (socket) { + socket.removeEventListener('message', term._getMessage); + } + + delete term.socket; +}; + +export function apply(terminalConstructor) { + /** + * Attaches the current terminal to the given socket + * + * @param {WebSocket} socket - The socket to attach the current terminal. + * @param {boolean} bidirectional - Whether the terminal should send data + * to the socket as well. + * @param {boolean} buffered - Whether the rendering of incoming data + * should happen instantly or at a maximum + * frequency of 1 rendering per 10ms. + */ + terminalConstructor.prototype.terminadoAttach = function(socket, bidirectional, buffered) { + return terminadoAttach(this, socket, bidirectional, buffered); + }; + + /** + * Detaches the current terminal from the given socket. + * + * @param {WebSocket} socket - The socket from which to detach the current + * terminal. + */ + terminalConstructor.prototype.terminadoDetach = function(socket) { + return terminadoDetach(this, socket); + }; +} diff --git a/xterm.js/src/addons/terminado/tsconfig.json b/xterm.js/src/addons/terminado/tsconfig.json new file mode 100644 index 0000000..775b20d --- /dev/null +++ b/xterm.js/src/addons/terminado/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "rootDir": ".", + "outDir": "../../../lib/addons/terminado/", + "sourceMap": true, + "removeComments": true + } +} diff --git a/xterm.js/src/addons/winptyCompat/package.json b/xterm.js/src/addons/winptyCompat/package.json new file mode 100644 index 0000000..2e9fc16 --- /dev/null +++ b/xterm.js/src/addons/winptyCompat/package.json @@ -0,0 +1,5 @@ +{ + "name": "xterm.winptyCompat", + "main": "winptyCompat.js", + "private": true +} diff --git a/xterm.js/src/addons/winptyCompat/tsconfig.json b/xterm.js/src/addons/winptyCompat/tsconfig.json new file mode 100644 index 0000000..e15a09a --- /dev/null +++ b/xterm.js/src/addons/winptyCompat/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "rootDir": ".", + "outDir": "../../../lib/addons/winptyCompat/", + "sourceMap": true, + "removeComments": true + } +} diff --git a/xterm.js/src/addons/winptyCompat/winptyCompat.test.ts b/xterm.js/src/addons/winptyCompat/winptyCompat.test.ts new file mode 100644 index 0000000..21e54e5 --- /dev/null +++ b/xterm.js/src/addons/winptyCompat/winptyCompat.test.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert, expect } from 'chai'; + +import * as winptyCompat from './winptyCompat' + +class MockTerminal {} + +describe('winptyCompat addon', () => { + describe('apply', () => { + it('should do register the `winptyCompatInit` method', () => { + winptyCompat.apply(MockTerminal); + assert.equal(typeof (MockTerminal).prototype.winptyCompatInit, 'function'); + }); + }); +}); diff --git a/xterm.js/src/addons/winptyCompat/winptyCompat.ts b/xterm.js/src/addons/winptyCompat/winptyCompat.ts new file mode 100644 index 0000000..723bf01 --- /dev/null +++ b/xterm.js/src/addons/winptyCompat/winptyCompat.ts @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +export function winptyCompatInit(terminal): void { + // Don't do anything when the platform is not Windows + const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].indexOf(navigator.platform) >= 0; + if (!isWindows) { + return; + } + + // Winpty does not support wraparound mode which means that lines will never + // be marked as wrapped. This causes issues for things like copying a line + // retaining the wrapped new line characters or if consumers are listening + // in on the data stream. + // + // The workaround for this is to listen to every incoming line feed and mark + // the line as wrapped if the last character in the previous line is not a + // space. This is certainly not without its problems, but generally on + // Windows when text reaches the end of the terminal it's likely going to be + // wrapped. + terminal.on('linefeed', () => { + const line = terminal.buffer.lines.get(terminal.buffer.ybase + terminal.buffer.y - 1); + const lastChar = line[terminal.cols - 1]; + + if (lastChar[3] !== 32 /* ' ' */) { + const nextLine = terminal.buffer.lines.get(terminal.buffer.ybase + terminal.buffer.y); + (nextLine).isWrapped = true; + } + }); +} + +export function apply(terminalConstructor) { + terminalConstructor.prototype.winptyCompatInit = function(): void { + winptyCompatInit(this); + }; +} diff --git a/xterm.js/src/addons/zmodem/demo/app.js b/xterm.js/src/addons/zmodem/demo/app.js new file mode 100644 index 0000000..31ecd7d --- /dev/null +++ b/xterm.js/src/addons/zmodem/demo/app.js @@ -0,0 +1,87 @@ +var express = require('express'); +var app = express(); +var expressWs = require('express-ws')(app); +var os = require('os'); +var pty = require('node-pty'); + +var terminals = {}, + logs = {}; + +app.use('/build', express.static(__dirname + '/../../../../build')); +app.use('/demo', express.static(__dirname + '/../../../../demo')); +app.use('/zmodemjs', express.static(__dirname + '/../../../../node_modules/zmodem.js/dist')); + +app.get('/', function(req, res){ + res.sendFile(__dirname + '/index.html'); +}); + +app.get('/style.css', function(req, res){ + res.sendFile(__dirname + '/style.css'); +}); + +app.get('/main.js', function(req, res){ + res.sendFile(__dirname + '/main.js'); +}); + +app.post('/terminals', function (req, res) { + var cols = parseInt(req.query.cols), + rows = parseInt(req.query.rows), + term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], { + encoding: null, + name: 'xterm-color', + cols: cols || 80, + rows: rows || 24, + cwd: process.env.PWD, + env: process.env + }); + + console.log('Created terminal with PID: ' + term.pid); + terminals[term.pid] = term; + logs[term.pid] = ''; + term.on('data', function(data) { + logs[term.pid] += data; + }); + res.send(term.pid.toString()); + res.end(); +}); + +app.post('/terminals/:pid/size', function (req, res) { + var pid = parseInt(req.params.pid), + cols = parseInt(req.query.cols), + rows = parseInt(req.query.rows), + term = terminals[pid]; + + term.resize(cols, rows); + console.log('Resized terminal ' + pid + ' to ' + cols + ' cols and ' + rows + ' rows.'); + res.end(); +}); + +app.ws('/terminals/:pid', function (ws, req) { + var term = terminals[parseInt(req.params.pid)]; + console.log('Connected to terminal ' + term.pid); + ws.send(logs[term.pid]); + + term.on('data', function(data) { + try { + ws.send(data); + } catch (ex) { + // The WebSocket is not open, ignore + } + }); + ws.on('message', function(msg) { + term.write(msg); + }); + ws.on('close', function () { + term.kill(); + console.log('Closed terminal ' + term.pid); + // Clean things up + delete terminals[term.pid]; + delete logs[term.pid]; + }); +}); + +var port = process.env.PORT || 3000, + host = os.platform() === 'win32' ? '127.0.0.1' : '0.0.0.0'; + +console.log('App listening to http://' + host + ':' + port); +app.listen(port, host); diff --git a/xterm.js/src/addons/zmodem/demo/index.html b/xterm.js/src/addons/zmodem/demo/index.html new file mode 100644 index 0000000..aee7742 --- /dev/null +++ b/xterm.js/src/addons/zmodem/demo/index.html @@ -0,0 +1,128 @@ + + + + xterm.js demo + + + + + + + + + + + + + + + + +

xterm.js: xterm, in the browser

+ +
+ +
+ + + + + + + + + +
+ +
+

Actions

+

+ + +

+
+
+

Options

+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+
+

Size

+
+
+ + +
+
+ + +
+
+
+
+

Attention: The demo is a barebones implementation and is designed for xterm.js evaluation purposes only. Exposing the demo to the public as is would introduce security risks for the host.

+

* ZMODEM file transfers are supported via an addon. To try it out, install lrzsz onto the remote peer, then run rz to send from your browser or sz <file> to send from the remote peer.

+ + + diff --git a/xterm.js/src/addons/zmodem/demo/main.js b/xterm.js/src/addons/zmodem/demo/main.js new file mode 100644 index 0000000..2a153fb --- /dev/null +++ b/xterm.js/src/addons/zmodem/demo/main.js @@ -0,0 +1,383 @@ +"use strict"; + +var term, + protocol, + socketURL, + socket, + pid; + +var terminalContainer = document.getElementById('terminal-container'), + actionElements = { + findNext: document.querySelector('#find-next'), + findPrevious: document.querySelector('#find-previous') + }, + optionElements = { + cursorBlink: document.querySelector('#option-cursor-blink'), + cursorStyle: document.querySelector('#option-cursor-style'), + scrollback: document.querySelector('#option-scrollback'), + tabstopwidth: document.querySelector('#option-tabstopwidth'), + bellStyle: document.querySelector('#option-bell-style') + }, + colsElement = document.getElementById('cols'), + rowsElement = document.getElementById('rows'); + +function setTerminalSize() { + var cols = parseInt(colsElement.value, 10); + var rows = parseInt(rowsElement.value, 10); + var viewportElement = document.querySelector('.xterm-viewport'); + var scrollBarWidth = viewportElement.offsetWidth - viewportElement.clientWidth; + var width = (cols * term.charMeasure.width + 20 /*room for scrollbar*/).toString() + 'px'; + var height = (rows * term.charMeasure.height).toString() + 'px'; + + terminalContainer.style.width = width; + terminalContainer.style.height = height; + term.resize(cols, rows); +} + +colsElement.addEventListener('change', setTerminalSize); +rowsElement.addEventListener('change', setTerminalSize); + +actionElements.findNext.addEventListener('keypress', function (e) { + if (e.key === "Enter") { + e.preventDefault(); + term.findNext(actionElements.findNext.value); + } +}); +actionElements.findPrevious.addEventListener('keypress', function (e) { + if (e.key === "Enter") { + e.preventDefault(); + term.findPrevious(actionElements.findPrevious.value); + } +}); + +optionElements.cursorBlink.addEventListener('change', function () { + term.setOption('cursorBlink', optionElements.cursorBlink.checked); +}); +optionElements.cursorStyle.addEventListener('change', function () { + term.setOption('cursorStyle', optionElements.cursorStyle.value); +}); +optionElements.bellStyle.addEventListener('change', function () { + term.setOption('bellStyle', optionElements.bellStyle.value); +}); +optionElements.scrollback.addEventListener('change', function () { + term.setOption('scrollback', parseInt(optionElements.scrollback.value, 10)); +}); +optionElements.tabstopwidth.addEventListener('change', function () { + term.setOption('tabStopWidth', parseInt(optionElements.tabstopwidth.value, 10)); +}); + +createTerminal(); + +function createTerminal() { + // Clean terminal + while (terminalContainer.children.length) { + terminalContainer.removeChild(terminalContainer.children[0]); + } + term = new Terminal({ + cursorBlink: optionElements.cursorBlink.checked, + scrollback: parseInt(optionElements.scrollback.value, 10), + tabStopWidth: parseInt(optionElements.tabstopwidth.value, 10) + }); + term.on('resize', function (size) { + if (!pid) { + return; + } + var cols = size.cols, + rows = size.rows, + url = '/terminals/' + pid + '/size?cols=' + cols + '&rows=' + rows; + + fetch(url, {method: 'POST'}); + }); + protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://'; + socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/terminals/'; + + term.open(terminalContainer); + term.fit(); + + // fit is called within a setTimeout, cols and rows need this. + setTimeout(function () { + colsElement.value = term.cols; + rowsElement.value = term.rows; + + // Set terminal size again to set the specific dimensions on the demo + setTerminalSize(); + + fetch('/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then(function (res) { + + res.text().then(function (pid) { + window.pid = pid; + socketURL += pid; + socket = new WebSocket(socketURL); + socket.onopen = runRealTerminal; + socket.onclose = runFakeTerminal; + socket.onerror = runFakeTerminal; + + term.zmodemAttach(socket, { + noTerminalWriteOutsideSession: true, + } ); + + term.on("zmodemRetract", () => { + start_form.style.display = "none"; + start_form.onsubmit = null; + }); + + term.on("zmodemDetect", (detection) => { + function do_zmodem() { + term.detach(); + let zsession = detection.confirm(); + + var promise; + + if (zsession.type === "receive") { + promise = _handle_receive_session(zsession); + } + else { + promise = _handle_send_session(zsession); + } + + promise.catch( console.error.bind(console) ).then( () => { + term.attach(socket); + } ); + } + + if (_auto_zmodem()) { + do_zmodem(); + } + else { + start_form.style.display = ""; + start_form.onsubmit = function(e) { + start_form.style.display = "none"; + + if (document.getElementById("zmstart_yes").checked) { + do_zmodem(); + } + else { + detection.deny(); + } + }; + } + }); + }); + }); + }, 0); +} + +//---------------------------------------------------------------------- +// UI STUFF + +function _show_file_info(xfer) { + var file_info = xfer.get_details(); + + document.getElementById("name").textContent = file_info.name; + document.getElementById("size").textContent = file_info.size; + document.getElementById("mtime").textContent = file_info.mtime; + document.getElementById("files_remaining").textContent = file_info.files_remaining; + document.getElementById("bytes_remaining").textContent = file_info.bytes_remaining; + + document.getElementById("mode").textContent = "0" + file_info.mode.toString(8); + + var xfer_opts = xfer.get_options(); + ["conversion", "management", "transport", "sparse"].forEach( (lbl) => { + document.getElementById(`zfile_${lbl}`).textContent = xfer_opts[lbl]; + } ); + + document.getElementById("zm_file").style.display = ""; +} +function _hide_file_info() { + document.getElementById("zm_file").style.display = "none"; +} + +function _save_to_disk(xfer, buffer) { + return Zmodem.Browser.save_to_disk(buffer, xfer.get_details().name); +} + +var skipper_button = document.getElementById("zm_progress_skipper"); +var skipper_button_orig_text = skipper_button.textContent; + +function _show_progress() { + skipper_button.disabled = false; + skipper_button.textContent = skipper_button_orig_text; + + document.getElementById("bytes_received").textContent = 0; + document.getElementById("percent_received").textContent = 0; + + document.getElementById("zm_progress").style.display = ""; +} + +function _update_progress(xfer) { + var total_in = xfer.get_offset(); + + document.getElementById("bytes_received").textContent = total_in; + + var percent_received = 100 * total_in / xfer.get_details().size; + document.getElementById("percent_received").textContent = percent_received.toFixed(2); +} + +function _hide_progress() { + document.getElementById("zm_progress").style.display = "none"; +} + +var start_form = document.getElementById("zm_start"); + +function _auto_zmodem() { + return document.getElementById("zmodem-auto").checked; +} + +// END UI STUFF +//---------------------------------------------------------------------- + +function _handle_receive_session(zsession) { + zsession.on("offer", function(xfer) { + current_receive_xfer = xfer; + + _show_file_info(xfer); + + var offer_form = document.getElementById("zm_offer"); + + function on_form_submit() { + offer_form.style.display = "none"; + + //START + //if (offer_form.zmaccept.value) { + if (_auto_zmodem() || document.getElementById("zmaccept_yes").checked) { + _show_progress(); + + var FILE_BUFFER = []; + xfer.on("input", (payload) => { + _update_progress(xfer); + FILE_BUFFER.push( new Uint8Array(payload) ); + }); + xfer.accept().then( + () => { + _save_to_disk(xfer, FILE_BUFFER); + }, + console.error.bind(console) + ); + } + else { + xfer.skip(); + } + //END + } + + if (_auto_zmodem()) { + on_form_submit(); + } + else { + offer_form.onsubmit = on_form_submit; + offer_form.style.display = ""; + } + } ); + + var promise = new Promise( (res) => { + zsession.on("session_end", () => { + _hide_file_info(); + _hide_progress(); + res(); + } ); + } ); + + zsession.start(); + + return promise; +} + +function _handle_send_session(zsession) { + var choose_form = document.getElementById("zm_choose"); + choose_form.style.display = ""; + + var file_el = document.getElementById("zm_files"); + + var promise = new Promise( (res) => { + file_el.onchange = function(e) { + choose_form.style.display = "none"; + + var files_obj = file_el.files; + + Zmodem.Browser.send_files( + zsession, + files_obj, + { + on_offer_response(obj, xfer) { + if (xfer) _show_progress(); + //console.log("offer", xfer ? "accepted" : "skipped"); + }, + on_progress(obj, xfer) { + _update_progress(xfer); + }, + on_file_complete(obj) { + //console.log("COMPLETE", obj); + _hide_progress(); + }, + } + ).then(_hide_progress).then( + zsession.close.bind(zsession), + console.error.bind(console) + ).then( () => { + _hide_file_info(); + _hide_progress(); + res(); + } ); + }; + } ); + + return promise; +} + +//This is here to allow canceling of an in-progress ZMODEM transfer. +var current_receive_xfer; + +//Called from HTML directly. +function skip_current_file() { + current_receive_xfer.skip(); + + skipper_button.disabled = true; + skipper_button.textContent = "Waiting for server to acknowledge skip …"; +} + +function runRealTerminal() { + term.attach(socket); + + term._initialized = true; +} + +function runFakeTerminal() { + if (term._initialized) { + return; + } + + term._initialized = true; + + var shellprompt = '$ '; + + term.prompt = function () { + term.write('\r\n' + shellprompt); + }; + + term.writeln('Welcome to xterm.js'); + term.writeln('This is a local terminal emulation, without a real terminal in the back-end.'); + term.writeln('Type some keys and commands to play around.'); + term.writeln(''); + term.prompt(); + + term.on('key', function (key, ev) { + var printable = ( + !ev.altKey && !ev.altGraphKey && !ev.ctrlKey && !ev.metaKey + ); + + if (ev.keyCode == 13) { + term.prompt(); + } else if (ev.keyCode == 8) { + // Do not delete the prompt + if (term.x > 2) { + term.write('\b \b'); + } + } else if (printable) { + term.write(key); + } + }); + + term.on('paste', function (data, ev) { + term.write(data); + }); +} diff --git a/xterm.js/src/addons/zmodem/package.json b/xterm.js/src/addons/zmodem/package.json new file mode 100644 index 0000000..218130a --- /dev/null +++ b/xterm.js/src/addons/zmodem/package.json @@ -0,0 +1,5 @@ +{ + "name": "xterm.zmodem", + "main": "zmodem.js", + "private": true +} diff --git a/xterm.js/src/addons/zmodem/tsconfig.json b/xterm.js/src/addons/zmodem/tsconfig.json new file mode 100644 index 0000000..9ded72e --- /dev/null +++ b/xterm.js/src/addons/zmodem/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "rootDir": ".", + "outDir": "../../../lib/addons/zmodem/", + "sourceMap": true, + "removeComments": true + } +} diff --git a/xterm.js/src/addons/zmodem/zmodem.test.ts b/xterm.js/src/addons/zmodem/zmodem.test.ts new file mode 100644 index 0000000..3cb2831 --- /dev/null +++ b/xterm.js/src/addons/zmodem/zmodem.test.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert, expect } from 'chai'; + +import * as zmodem from './zmodem' + +class MockTerminal {} + +describe('zmodem addon', () => { + describe('apply', () => { + it('should do register the `zmodemAttach` method and `zmodemBrowser` attribute', () => { + zmodem.apply(MockTerminal); + assert.equal(typeof (MockTerminal).prototype.zmodemAttach, 'function'); + assert.equal(typeof (MockTerminal).prototype.zmodemBrowser, 'object'); + }); + }); +}); diff --git a/xterm.js/src/addons/zmodem/zmodem.ts b/xterm.js/src/addons/zmodem/zmodem.ts new file mode 100644 index 0000000..57bdde3 --- /dev/null +++ b/xterm.js/src/addons/zmodem/zmodem.ts @@ -0,0 +1,90 @@ +/** + * + * Allow xterm.js to handle ZMODEM uploads and downloads. + * + * This addon is a wrapper around zmodem.js. It adds the following to the + * Terminal class: + * + * - function `zmodemAttach(, )` - creates a Zmodem.Sentry + * on the passed WebSocket object. The Object passed is optional and + * can contain: + * - noTerminalWriteOutsideSession: Suppress writes from the Sentry + * object to the Terminal while there is no active Session. This + * is necessary for compatibility with, for example, the + * `attach.js` addon. + * + * - event `zmodemDetect` - fired on Zmodem.Sentry’s `on_detect` callback. + * Passes the zmodem.js Detection object. + * + * - event `zmodemRetract` - fired on Zmodem.Sentry’s `on_retract` callback. + * + * You’ll need to provide logic to handle uploads and downloads. + * See zmodem.js’s documentation for more details. + * + * **IMPORTANT:** After you confirm() a zmodem.js Detection, if you have + * used the `attach` or `terminado` addons, you’ll need to suspend their + * operation for the duration of the ZMODEM session. (The demo does this + * via `detach()` and a re-`attach()`.) + */ + +let Zmodem; + +export function zmodemAttach(term, ws, opts) { + if (!opts) opts = {}; + + var senderFunc = function _ws_sender_func(octets) { + ws.send(new Uint8Array(octets)); + }; + + var zsentry; + + function _shouldWrite() { + return !!zsentry.get_confirmed_session() || !opts.noTerminalWriteOutsideSession; + } + + zsentry = new Zmodem.Sentry( { + to_terminal: function _to_terminal(octets) { + if (_shouldWrite()) { + term.write( + String.fromCharCode.apply(String, octets) + ); + } + }, + + sender: senderFunc, + + on_retract: function _on_retract() { + term.emit('zmodemRetract'); + }, + + on_detect: function _on_detect(detection) { + term.emit('zmodemDetect', detection); + }, + } ); + + function handleWSMessage(evt) { + + //In testing with xterm.js’s demo the first message was + //always text even if the rest were binary. While that + //may be specific to xterm.js’s demo, ultimately we + //should reject anything that isn’t binary. + if (typeof evt.data === 'string') { + if (_shouldWrite()) { + term.write(evt.data); + } + } + else { + zsentry.consume(evt.data); + } + } + + ws.binaryType = 'arraybuffer'; + ws.addEventListener('message', handleWSMessage); +} + +export function apply(terminalConstructor) { + Zmodem = (typeof window == 'object') ? (window).ZModem : {Browser: null}; // Nullify browser for tests + + terminalConstructor.prototype.zmodemAttach = zmodemAttach.bind(this, this); + terminalConstructor.prototype.zmodemBrowser = Zmodem.Browser +} diff --git a/xterm.js/src/handlers/Clipboard.test.ts b/xterm.js/src/handlers/Clipboard.test.ts new file mode 100644 index 0000000..d35e5fa --- /dev/null +++ b/xterm.js/src/handlers/Clipboard.test.ts @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert } from 'chai'; +import * as Terminal from '../Terminal'; +import * as Clipboard from './Clipboard'; + +describe('evaluatePastedTextProcessing', () => { + it('should replace carriage return + line feed with line feed on windows', () => { + const pastedText = 'foo\r\nbar\r\n'; + const processedText = Clipboard.prepareTextForTerminal(pastedText, false); + const windowsProcessedText = Clipboard.prepareTextForTerminal(pastedText, true); + + assert.equal(processedText, 'foo\r\nbar\r\n'); + assert.equal(windowsProcessedText, 'foo\rbar\r'); + }); + it('should bracket pasted text in bracketedPasteMode', () => { + const pastedText = 'foo bar'; + const unbracketedText = Clipboard.bracketTextForPaste(pastedText, false); + const bracketedText = Clipboard.bracketTextForPaste(pastedText, true); + + assert.equal(unbracketedText, 'foo bar'); + assert.equal(bracketedText, '\x1b[200~foo bar\x1b[201~'); + }); +}); diff --git a/xterm.js/src/handlers/Clipboard.ts b/xterm.js/src/handlers/Clipboard.ts new file mode 100644 index 0000000..cf6661f --- /dev/null +++ b/xterm.js/src/handlers/Clipboard.ts @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ITerminal, ISelectionManager } from '../Interfaces'; + +interface IWindow extends Window { + clipboardData?: { + getData(format: string): string; + setData(format: string, data: string): void; + }; +} + +declare var window: IWindow; + +/** + * Prepares text to be pasted into the terminal by normalizing the line endings + * @param text The pasted text that needs processing before inserting into the terminal + */ +export function prepareTextForTerminal(text: string, isMSWindows: boolean): string { + if (isMSWindows) { + return text.replace(/\r?\n/g, '\r'); + } + return text; +} + +/** + * Bracket text for paste, if necessary, as per https://cirw.in/blog/bracketed-paste + * @param text The pasted text to bracket + */ +export function bracketTextForPaste(text: string, bracketedPasteMode: boolean): string { + if (bracketedPasteMode) { + return '\x1b[200~' + text + '\x1b[201~'; + } + return text; +} + +/** + * Binds copy functionality to the given terminal. + * @param {ClipboardEvent} ev The original copy event to be handled + */ +export function copyHandler(ev: ClipboardEvent, term: ITerminal, selectionManager: ISelectionManager): void { + if (term.browser.isMSIE) { + window.clipboardData.setData('Text', selectionManager.selectionText); + } else { + ev.clipboardData.setData('text/plain', selectionManager.selectionText); + } + + // Prevent or the original text will be copied. + ev.preventDefault(); +} + +/** + * Redirect the clipboard's data to the terminal's input handler. + * @param {ClipboardEvent} ev The original paste event to be handled + * @param {Terminal} term The terminal on which to apply the handled paste event + */ +export function pasteHandler(ev: ClipboardEvent, term: ITerminal): void { + ev.stopPropagation(); + + let text: string; + + let dispatchPaste = function(text: string): void { + text = prepareTextForTerminal(text, term.browser.isMSWindows); + text = bracketTextForPaste(text, term.bracketedPasteMode); + term.handler(text); + term.textarea.value = ''; + term.emit('paste', text); + term.cancel(ev); + }; + + if (term.browser.isMSIE) { + if (window.clipboardData) { + text = window.clipboardData.getData('Text'); + dispatchPaste(text); + } + } else { + if (ev.clipboardData) { + text = ev.clipboardData.getData('text/plain'); + dispatchPaste(text); + } + } +} + +/** + * Moves the textarea under the mouse cursor and focuses it. + * @param ev The original right click event to be handled. + * @param textarea The terminal's textarea. + */ +export function moveTextAreaUnderMouseCursor(ev: MouseEvent, textarea: HTMLTextAreaElement): void { + // Bring textarea at the cursor position + textarea.style.position = 'fixed'; + textarea.style.width = '20px'; + textarea.style.height = '20px'; + textarea.style.left = (ev.clientX - 10) + 'px'; + textarea.style.top = (ev.clientY - 10) + 'px'; + textarea.style.zIndex = '1000'; + + textarea.focus(); + + // Reset the terminal textarea's styling + setTimeout(() => { + textarea.style.position = null; + textarea.style.width = null; + textarea.style.height = null; + textarea.style.left = null; + textarea.style.top = null; + textarea.style.zIndex = null; + }, 4); +} + +/** + * Bind to right-click event and allow right-click copy and paste. + * @param ev The original right click event to be handled. + * @param textarea The terminal's textarea. + * @param selectionManager The terminal's selection manager. + */ +export function rightClickHandler(ev: MouseEvent, textarea: HTMLTextAreaElement, selectionManager: ISelectionManager): void { + moveTextAreaUnderMouseCursor(ev, textarea); + + // Get textarea ready to copy from the context menu + textarea.value = selectionManager.selectionText; + textarea.select(); +} diff --git a/xterm.js/src/input/Interfaces.ts b/xterm.js/src/input/Interfaces.ts new file mode 100644 index 0000000..21514a5 --- /dev/null +++ b/xterm.js/src/input/Interfaces.ts @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +export interface IMouseZoneManager { + add(zone: IMouseZone): void; + clearAll(start?: number, end?: number): void; +} + +export interface IMouseZone { + x1: number; + x2: number; + y: number; + clickCallback: (e: MouseEvent) => any; + hoverCallback?: (e: MouseEvent) => any; + tooltipCallback?: (e: MouseEvent) => any; + leaveCallback?: () => any; +} diff --git a/xterm.js/src/input/MouseZoneManager.ts b/xterm.js/src/input/MouseZoneManager.ts new file mode 100644 index 0000000..8fae317 --- /dev/null +++ b/xterm.js/src/input/MouseZoneManager.ts @@ -0,0 +1,197 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { IMouseZoneManager, IMouseZone } from './Interfaces'; +import { ITerminal } from '../Interfaces'; + +const HOVER_DURATION = 500; + +/** + * The MouseZoneManager allows components to register zones within the terminal + * that trigger hover and click callbacks. + * + * This class was intentionally made not so robust initially as the only case it + * needed to support was single-line links which never overlap. Improvements can + * be made in the future. + */ +export class MouseZoneManager implements IMouseZoneManager { + private _zones: IMouseZone[] = []; + + private _areZonesActive: boolean = false; + private _mouseMoveListener: (e: MouseEvent) => any; + private _clickListener: (e: MouseEvent) => any; + + private _tooltipTimeout: number = null; + private _currentZone: IMouseZone = null; + private _lastHoverCoords: [number, number] = [null, null]; + + constructor( + private _terminal: ITerminal + ) { + this._terminal.element.addEventListener('mousedown', e => this._onMouseDown(e)); + + // These events are expensive, only listen to it when mouse zones are active + this._mouseMoveListener = e => this._onMouseMove(e); + this._clickListener = e => this._onClick(e); + } + + public add(zone: IMouseZone): void { + this._zones.push(zone); + if (this._zones.length === 1) { + this._activate(); + } + } + + public clearAll(start?: number, end?: number): void { + // Exit if there's nothing to clear + if (this._zones.length === 0) { + return; + } + + // Clear all if start/end weren't set + if (!end) { + start = 0; + end = this._terminal.rows - 1; + } + + // Iterate through zones and clear them out if they're within the range + for (let i = 0; i < this._zones.length; i++) { + const zone = this._zones[i]; + if (zone.y > start && zone.y <= end + 1) { + if (this._currentZone && this._currentZone === zone) { + this._currentZone.leaveCallback(); + this._currentZone = null; + } + this._zones.splice(i--, 1); + } + } + + // Deactivate the mouse zone manager if all the zones have been removed + if (this._zones.length === 0) { + this._deactivate(); + } + } + + private _activate(): void { + if (!this._areZonesActive) { + this._areZonesActive = true; + this._terminal.element.addEventListener('mousemove', this._mouseMoveListener); + this._terminal.element.addEventListener('click', this._clickListener); + } + } + + private _deactivate(): void { + if (this._areZonesActive) { + this._areZonesActive = false; + this._terminal.element.removeEventListener('mousemove', this._mouseMoveListener); + this._terminal.element.removeEventListener('click', this._clickListener); + } + } + + private _onMouseMove(e: MouseEvent): void { + // TODO: Ideally this would only clear the hover state when the mouse moves + // outside of the mouse zone + if (this._lastHoverCoords[0] !== e.pageX || this._lastHoverCoords[1] !== e.pageY) { + this._onHover(e); + // Record the current coordinates + this._lastHoverCoords = [e.pageX, e.pageY]; + } + } + + private _onHover(e: MouseEvent): void { + const zone = this._findZoneEventAt(e); + + // Do nothing if the zone is the same + if (zone === this._currentZone) { + return; + } + + // Fire the hover end callback and cancel any existing timer if a new zone + // is being hovered + if (this._currentZone) { + this._currentZone.leaveCallback(); + this._currentZone = null; + if (this._tooltipTimeout) { + clearTimeout(this._tooltipTimeout); + } + } + + // Exit if there is not zone + if (!zone) { + return; + } + this._currentZone = zone; + + // Trigger the hover callback + if (zone.hoverCallback) { + zone.hoverCallback(e); + } + + // Restart the tooltip timeout + this._tooltipTimeout = setTimeout(() => this._onTooltip(e), HOVER_DURATION); + } + + private _onTooltip(e: MouseEvent): void { + this._tooltipTimeout = null; + const zone = this._findZoneEventAt(e); + if (zone && zone.tooltipCallback) { + zone.tooltipCallback(e); + } + } + + private _onMouseDown(e: MouseEvent): void { + // Ignore the event if there are no zones active + if (!this._areZonesActive) { + return; + } + + // Find the active zone, prevent event propagation if found to prevent other + // components from handling the mouse event. + const zone = this._findZoneEventAt(e); + if (zone) { + // TODO: When link modifier support is added, the event should only be + // cancelled when the modifier is held (see #1021) + e.preventDefault(); + e.stopImmediatePropagation(); + } + } + + private _onClick(e: MouseEvent): void { + // Find the active zone and click it if found + const zone = this._findZoneEventAt(e); + if (zone) { + zone.clickCallback(e); + e.preventDefault(); + e.stopImmediatePropagation(); + } + } + + private _findZoneEventAt(e: MouseEvent): IMouseZone { + const coords = this._terminal.mouseHelper.getCoords(e, this._terminal.element, this._terminal.charMeasure, this._terminal.options.lineHeight, this._terminal.cols, this._terminal.rows); + if (!coords) { + return null; + } + for (let i = 0; i < this._zones.length; i++) { + const zone = this._zones[i]; + if (zone.y === coords[1] && zone.x1 <= coords[0] && zone.x2 > coords[0]) { + return zone; + } + }; + return null; + } +} + +export class MouseZone implements IMouseZone { + constructor( + public x1: number, + public x2: number, + public y: number, + public clickCallback: (e: MouseEvent) => any, + public hoverCallback?: (e: MouseEvent) => any, + public tooltipCallback?: (e: MouseEvent) => any, + public leaveCallback?: () => void + ) { + } +} diff --git a/xterm.js/src/renderer/BaseRenderLayer.ts b/xterm.js/src/renderer/BaseRenderLayer.ts new file mode 100644 index 0000000..b4becbc --- /dev/null +++ b/xterm.js/src/renderer/BaseRenderLayer.ts @@ -0,0 +1,336 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { IRenderLayer, IColorSet, IRenderDimensions } from './Interfaces'; +import { ITerminal, ITerminalOptions } from '../Interfaces'; +import { acquireCharAtlas, CHAR_ATLAS_CELL_SPACING } from './CharAtlas'; +import { CharData } from '../Types'; +import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer'; + +export const INVERTED_DEFAULT_COLOR = -1; +const DIM_OPACITY = 0.5; + +export abstract class BaseRenderLayer implements IRenderLayer { + private _canvas: HTMLCanvasElement; + protected _ctx: CanvasRenderingContext2D; + private _scaledCharWidth: number = 0; + private _scaledCharHeight: number = 0; + private _scaledCellWidth: number = 0; + private _scaledCellHeight: number = 0; + private _scaledCharLeft: number = 0; + private _scaledCharTop: number = 0; + + private _charAtlas: HTMLCanvasElement | ImageBitmap; + + constructor( + container: HTMLElement, + id: string, + zIndex: number, + private _alpha: boolean, + protected _colors: IColorSet + ) { + this._canvas = document.createElement('canvas'); + this._canvas.id = `xterm-${id}-layer`; + this._canvas.style.zIndex = zIndex.toString(); + this._ctx = this._canvas.getContext('2d', {alpha: _alpha}); + this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); + // Draw the background if this is an opaque layer + if (!_alpha) { + this.clearAll(); + } + container.appendChild(this._canvas); + } + + public onOptionsChanged(terminal: ITerminal): void {} + public onBlur(terminal: ITerminal): void {} + public onFocus(terminal: ITerminal): void {} + public onCursorMove(terminal: ITerminal): void {} + public onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void {} + public onSelectionChanged(terminal: ITerminal, start: [number, number], end: [number, number]): void {} + + public onThemeChanged(terminal: ITerminal, colorSet: IColorSet): void { + this._refreshCharAtlas(terminal, colorSet); + } + + /** + * Refreshes the char atlas, aquiring a new one if necessary. + * @param terminal The terminal. + * @param colorSet The color set to use for the char atlas. + */ + private _refreshCharAtlas(terminal: ITerminal, colorSet: IColorSet): void { + if (this._scaledCharWidth <= 0 && this._scaledCharHeight <= 0) { + return; + } + this._charAtlas = null; + const result = acquireCharAtlas(terminal, this._colors, this._scaledCharWidth, this._scaledCharHeight); + if (result instanceof HTMLCanvasElement) { + this._charAtlas = result; + } else { + result.then(bitmap => this._charAtlas = bitmap); + } + } + + public resize(terminal: ITerminal, dim: IRenderDimensions, charSizeChanged: boolean): void { + this._scaledCellWidth = dim.scaledCellWidth; + this._scaledCellHeight = dim.scaledCellHeight; + this._scaledCharWidth = dim.scaledCharWidth; + this._scaledCharHeight = dim.scaledCharHeight; + this._scaledCharLeft = dim.scaledCharLeft; + this._scaledCharTop = dim.scaledCharTop; + this._canvas.width = dim.scaledCanvasWidth; + this._canvas.height = dim.scaledCanvasHeight; + this._canvas.style.width = `${dim.canvasWidth}px`; + this._canvas.style.height = `${dim.canvasHeight}px`; + + // Draw the background if this is an opaque layer + if (!this._alpha) { + this.clearAll(); + } + + if (charSizeChanged) { + this._refreshCharAtlas(terminal, this._colors); + } + } + + public abstract reset(terminal: ITerminal): void; + + /** + * Fills 1+ cells completely. This uses the existing fillStyle on the context. + * @param x The column to start at. + * @param y The row to start at + * @param width The number of columns to fill. + * @param height The number of rows to fill. + */ + protected fillCells(x: number, y: number, width: number, height: number): void { + this._ctx.fillRect( + x * this._scaledCellWidth, + y * this._scaledCellHeight, + width * this._scaledCellWidth, + height * this._scaledCellHeight); + } + + /** + * Fills a 1px line (2px on HDPI) at the bottom of the cell. This uses the + * existing fillStyle on the context. + * @param x The column to fill. + * @param y The row to fill. + */ + protected fillBottomLineAtCells(x: number, y: number, width: number = 1): void { + this._ctx.fillRect( + x * this._scaledCellWidth, + (y + 1) * this._scaledCellHeight - window.devicePixelRatio - 1 /* Ensure it's drawn within the cell */, + width * this._scaledCellWidth, + window.devicePixelRatio); + } + + /** + * Fills a 1px line (2px on HDPI) at the left of the cell. This uses the + * existing fillStyle on the context. + * @param x The column to fill. + * @param y The row to fill. + */ + protected fillLeftLineAtCell(x: number, y: number): void { + this._ctx.fillRect( + x * this._scaledCellWidth, + y * this._scaledCellHeight, + window.devicePixelRatio, + this._scaledCellHeight); + } + + /** + * Strokes a 1px rectangle (2px on HDPI) around a cell. This uses the existing + * strokeStyle on the context. + * @param x The column to fill. + * @param y The row to fill. + */ + protected strokeRectAtCell(x: number, y: number, width: number, height: number): void { + this._ctx.lineWidth = window.devicePixelRatio; + this._ctx.strokeRect( + x * this._scaledCellWidth + window.devicePixelRatio / 2, + y * this._scaledCellHeight + (window.devicePixelRatio / 2), + width * this._scaledCellWidth - window.devicePixelRatio, + (height * this._scaledCellHeight) - window.devicePixelRatio); + } + + /** + * Clears the entire canvas. + */ + protected clearAll(): void { + if (this._alpha) { + this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); + } else { + this._ctx.fillStyle = this._colors.background; + this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height); + } + } + + /** + * Clears 1+ cells completely. + * @param x The column to start at. + * @param y The row to start at. + * @param width The number of columns to clear. + * @param height The number of rows to clear. + */ + protected clearCells(x: number, y: number, width: number, height: number): void { + if (this._alpha) { + this._ctx.clearRect( + x * this._scaledCellWidth, + y * this._scaledCellHeight, + width * this._scaledCellWidth, + height * this._scaledCellHeight); + } else { + this._ctx.fillStyle = this._colors.background; + this._ctx.fillRect( + x * this._scaledCellWidth, + y * this._scaledCellHeight, + width * this._scaledCellWidth, + height * this._scaledCellHeight); + } + } + + /** + * Draws a truecolor character at the cell. The character will be clipped to + * ensure that it fits with the cell, including the cell to the right if it's + * a wide character. This uses the existing fillStyle on the context. + * @param terminal The terminal. + * @param charData The char data for the character to draw. + * @param x The column to draw at. + * @param y The row to draw at. + * @param color The color of the character. + */ + protected fillCharTrueColor(terminal: ITerminal, charData: CharData, x: number, y: number): void { + this._ctx.font = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`; + this._ctx.textBaseline = 'top'; + this._clipRow(terminal, y); + this._ctx.fillText( + charData[CHAR_DATA_CHAR_INDEX], + x * this._scaledCellWidth + this._scaledCharLeft, + y * this._scaledCellHeight + this._scaledCharTop); + } + + /** + * Draws a character at a cell. If possible this will draw using the character + * atlas to reduce draw time. + * @param terminal The terminal. + * @param char The character. + * @param code The character code. + * @param width The width of the character. + * @param x The column to draw at. + * @param y The row to draw at. + * @param fg The foreground color, in the format stored within the attributes. + * @param bg The background color, in the format stored within the attributes. + * This is used to validate whether a cached image can be used. + * @param bold Whether the text is bold. + */ + protected drawChar(terminal: ITerminal, char: string, code: number, width: number, x: number, y: number, fg: number, bg: number, bold: boolean, dim: boolean): void { + let colorIndex = 0; + if (fg < 256) { + colorIndex = fg + 2; + } else { + // If default color and bold + if (bold && terminal.options.enableBold) { + colorIndex = 1; + } + } + const isAscii = code < 256; + // A color is basic if it is one of the standard normal or bold weight + // colors of the characters held in the char atlas. Note that this excludes + // the normal weight _light_ color characters. + const isBasicColor = (colorIndex > 1 && fg < 16) && (fg < 8 || bold); + const isDefaultColor = fg >= 256; + const isDefaultBackground = bg >= 256; + if (this._charAtlas && isAscii && (isBasicColor || isDefaultColor) && isDefaultBackground) { + // ImageBitmap's draw about twice as fast as from a canvas + const charAtlasCellWidth = this._scaledCharWidth + CHAR_ATLAS_CELL_SPACING; + const charAtlasCellHeight = this._scaledCharHeight + CHAR_ATLAS_CELL_SPACING; + + // Apply alpha to dim the character + if (dim) { + this._ctx.globalAlpha = DIM_OPACITY; + } + + // Draw the non-bold version of the same color if bold is not enabled + if (bold && !terminal.options.enableBold) { + // Ignore default color as it's not touched above + if (colorIndex > 1) { + colorIndex -= 8; + } + } + + this._ctx.drawImage(this._charAtlas, + code * charAtlasCellWidth, + colorIndex * charAtlasCellHeight, + charAtlasCellWidth, + this._scaledCharHeight, + x * this._scaledCellWidth + this._scaledCharLeft, + y * this._scaledCellHeight + this._scaledCharTop, + charAtlasCellWidth, + this._scaledCharHeight); + } else { + this._drawUncachedChar(terminal, char, width, fg, x, y, bold, dim); + } + // This draws the atlas (for debugging purposes) + // this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); + // this._ctx.drawImage(this._charAtlas, 0, 0); + } + + /** + * Draws a character at a cell. The character will be clipped to + * ensure that it fits with the cell, including the cell to the right if it's + * a wide character. + * @param terminal The terminal. + * @param char The character. + * @param width The width of the character. + * @param fg The foreground color, in the format stored within the attributes. + * @param x The column to draw at. + * @param y The row to draw at. + */ + private _drawUncachedChar(terminal: ITerminal, char: string, width: number, fg: number, x: number, y: number, bold: boolean, dim: boolean): void { + this._ctx.save(); + this._ctx.font = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`; + if (bold && terminal.options.enableBold) { + this._ctx.font = `bold ${this._ctx.font}`; + } + this._ctx.textBaseline = 'top'; + + if (fg === INVERTED_DEFAULT_COLOR) { + this._ctx.fillStyle = this._colors.background; + } else if (fg < 256) { + // 256 color support + this._ctx.fillStyle = this._colors.ansi[fg]; + } else { + this._ctx.fillStyle = this._colors.foreground; + } + + this._clipRow(terminal, y); + + // Apply alpha to dim the character + if (dim) { + this._ctx.globalAlpha = DIM_OPACITY; + } + // Draw the character + this._ctx.fillText( + char, + x * this._scaledCellWidth + this._scaledCharLeft, + y * this._scaledCellHeight + this._scaledCharTop); + this._ctx.restore(); + } + + /** + * Clips a row to ensure no pixels will be drawn outside the cells in the row. + * @param terminal The terminal. + * @param y The row to clip. + */ + private _clipRow(terminal: ITerminal, y: number): void { + this._ctx.beginPath(); + this._ctx.rect( + 0, + y * this._scaledCellHeight, + terminal.cols * this._scaledCellWidth, + this._scaledCellHeight); + this._ctx.clip(); + } +} + diff --git a/xterm.js/src/renderer/CharAtlas.ts b/xterm.js/src/renderer/CharAtlas.ts new file mode 100644 index 0000000..8cd0911 --- /dev/null +++ b/xterm.js/src/renderer/CharAtlas.ts @@ -0,0 +1,222 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ITerminal, ITheme } from '../Interfaces'; +import { IColorSet } from '../renderer/Interfaces'; +import { isFirefox } from '../utils/Browser'; + +export const CHAR_ATLAS_CELL_SPACING = 1; + +interface ICharAtlasConfig { + fontSize: number; + fontFamily: string; + scaledCharWidth: number; + scaledCharHeight: number; + colors: IColorSet; +} + +interface ICharAtlasCacheEntry { + bitmap: HTMLCanvasElement | Promise; + config: ICharAtlasConfig; + ownedBy: ITerminal[]; +} + +let charAtlasCache: ICharAtlasCacheEntry[] = []; + +/** + * Acquires a char atlas, either generating a new one or returning an existing + * one that is in use by another terminal. + * @param terminal The terminal. + * @param colors The colors to use. + */ +export function acquireCharAtlas(terminal: ITerminal, colors: IColorSet, scaledCharWidth: number, scaledCharHeight: number): HTMLCanvasElement | Promise { + const newConfig = generateConfig(scaledCharWidth, scaledCharHeight, terminal, colors); + + // Check to see if the terminal already owns this config + for (let i = 0; i < charAtlasCache.length; i++) { + const entry = charAtlasCache[i]; + const ownedByIndex = entry.ownedBy.indexOf(terminal); + if (ownedByIndex >= 0) { + if (configEquals(entry.config, newConfig)) { + return entry.bitmap; + } else { + // The configs differ, release the terminal from the entry + if (entry.ownedBy.length === 1) { + charAtlasCache.splice(i, 1); + } else { + entry.ownedBy.splice(ownedByIndex, 1); + } + break; + } + } + } + + // Try match a char atlas from the cache + for (let i = 0; i < charAtlasCache.length; i++) { + const entry = charAtlasCache[i]; + if (configEquals(entry.config, newConfig)) { + // Add the terminal to the cache entry and return + entry.ownedBy.push(terminal); + return entry.bitmap; + } + } + + const newEntry: ICharAtlasCacheEntry = { + bitmap: generator.generate(scaledCharWidth, scaledCharHeight, terminal.options.fontSize, terminal.options.fontFamily, colors.background, colors.foreground, colors.ansi), + config: newConfig, + ownedBy: [terminal] + }; + charAtlasCache.push(newEntry); + return newEntry.bitmap; +} + +function generateConfig(scaledCharWidth: number, scaledCharHeight: number, terminal: ITerminal, colors: IColorSet): ICharAtlasConfig { + const clonedColors = { + foreground: colors.foreground, + background: colors.background, + cursor: null, + cursorAccent: null, + selection: null, + ansi: colors.ansi.slice(0, 16) + }; + return { + scaledCharWidth, + scaledCharHeight, + fontFamily: terminal.options.fontFamily, + fontSize: terminal.options.fontSize, + colors: clonedColors + }; +} + +function configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean { + for (let i = 0; i < a.colors.ansi.length; i++) { + if (a.colors.ansi[i] !== b.colors.ansi[i]) { + return false; + } + } + return a.fontFamily === b.fontFamily && + a.fontSize === b.fontSize && + a.scaledCharWidth === b.scaledCharWidth && + a.scaledCharHeight === b.scaledCharHeight && + a.colors.foreground === b.colors.foreground && + a.colors.background === b.colors.background; +} + +let generator: CharAtlasGenerator; + +/** + * Initializes the char atlas generator. + * @param document The document. + */ +export function initialize(document: Document, alpha: boolean): void { + if (!generator) { + generator = new CharAtlasGenerator(document, alpha); + } +} + +class CharAtlasGenerator { + private _canvas: HTMLCanvasElement; + private _ctx: CanvasRenderingContext2D; + + constructor(private _document: Document, alpha: boolean) { + this._canvas = this._document.createElement('canvas'); + this._ctx = this._canvas.getContext('2d', {alpha}); + this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); + } + + public generate(scaledCharWidth: number, scaledCharHeight: number, fontSize: number, fontFamily: string, background: string, foreground: string, ansiColors: string[]): HTMLCanvasElement | Promise { + const cellWidth = scaledCharWidth + CHAR_ATLAS_CELL_SPACING; + const cellHeight = scaledCharHeight + CHAR_ATLAS_CELL_SPACING; + this._canvas.width = 255 * cellWidth; + this._canvas.height = (/*default+default bold*/2 + /*0-15*/16) * cellHeight; + + this._ctx.fillStyle = background; + this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height); + + this._ctx.save(); + this._ctx.fillStyle = foreground; + this._ctx.font = `${fontSize * window.devicePixelRatio}px ${fontFamily}`; + this._ctx.textBaseline = 'top'; + + // Default color + for (let i = 0; i < 256; i++) { + this._ctx.save(); + this._ctx.beginPath(); + this._ctx.rect(i * cellWidth, 0, cellWidth, cellHeight); + this._ctx.clip(); + this._ctx.fillText(String.fromCharCode(i), i * cellWidth, 0); + this._ctx.restore(); + } + // Default color bold + this._ctx.save(); + this._ctx.font = `bold ${this._ctx.font}`; + for (let i = 0; i < 256; i++) { + this._ctx.save(); + this._ctx.beginPath(); + this._ctx.rect(i * cellWidth, cellHeight, cellWidth, cellHeight); + this._ctx.clip(); + this._ctx.fillText(String.fromCharCode(i), i * cellWidth, cellHeight); + this._ctx.restore(); + } + this._ctx.restore(); + + // Colors 0-15 + this._ctx.font = `${fontSize * window.devicePixelRatio}px ${fontFamily}`; + for (let colorIndex = 0; colorIndex < 16; colorIndex++) { + // colors 8-15 are bold + if (colorIndex === 8) { + this._ctx.font = `bold ${this._ctx.font}`; + } + const y = (colorIndex + 2) * cellHeight; + // Draw ascii characters + for (let i = 0; i < 256; i++) { + this._ctx.save(); + this._ctx.beginPath(); + this._ctx.rect(i * cellWidth, y, cellWidth, cellHeight); + this._ctx.clip(); + this._ctx.fillStyle = ansiColors[colorIndex]; + this._ctx.fillText(String.fromCharCode(i), i * cellWidth, y); + this._ctx.restore(); + } + } + this._ctx.restore(); + + // Support is patchy for createImageBitmap at the moment, pass a canvas back + // if support is lacking as drawImage works there too. Firefox is also + // included here as ImageBitmap appears both buggy and has horrible + // performance (tested on v55). + if (!('createImageBitmap' in window) || isFirefox) { + // Regenerate canvas and context as they are now owned by the char atlas + const result = this._canvas; + this._canvas = this._document.createElement('canvas'); + this._ctx = this._canvas.getContext('2d'); + this._ctx.scale(window.devicePixelRatio, window.devicePixelRatio); + return result; + } + + const charAtlasImageData = this._ctx.getImageData(0, 0, this._canvas.width, this._canvas.height); + + // Remove the background color from the image so characters may overlap + const r = parseInt(background.substr(1, 2), 16); + const g = parseInt(background.substr(3, 2), 16); + const b = parseInt(background.substr(5, 2), 16); + this._clearColor(charAtlasImageData, r, g, b); + + const promise = window.createImageBitmap(charAtlasImageData); + // Clear the rect while the promise is in progress + this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); + return promise; + } + + private _clearColor(imageData: ImageData, r: number, g: number, b: number): void { + for (let offset = 0; offset < imageData.data.length; offset += 4) { + if (imageData.data[offset] === r && + imageData.data[offset + 1] === g && + imageData.data[offset + 2] === b) { + imageData.data[offset + 3] = 0; + } + } + } +} diff --git a/xterm.js/src/renderer/ColorManager.test.ts b/xterm.js/src/renderer/ColorManager.test.ts new file mode 100644 index 0000000..2240760 --- /dev/null +++ b/xterm.js/src/renderer/ColorManager.test.ts @@ -0,0 +1,295 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert } from 'chai'; +import { ColorManager } from './ColorManager'; + +describe('ColorManager', () => { + let cm: ColorManager; + + beforeEach(() => { + cm = new ColorManager(); + }); + + describe('constructor', () => { + it('should fill all colors with values', () => { + for (let key in cm.colors) { + if (typeof key === 'string') { + // A #rrggbb or rgba(...) + assert.ok(cm.colors[key].length >= 7); + } + } + assert.equal(cm.colors.ansi.length, 256); + }); + + it('should fill 240 colors with expected values', () => { + assert.equal(cm.colors.ansi[16], '#000000'); + assert.equal(cm.colors.ansi[17], '#00005f'); + assert.equal(cm.colors.ansi[18], '#000087'); + assert.equal(cm.colors.ansi[19], '#0000af'); + assert.equal(cm.colors.ansi[20], '#0000d7'); + assert.equal(cm.colors.ansi[21], '#0000ff'); + assert.equal(cm.colors.ansi[22], '#005f00'); + assert.equal(cm.colors.ansi[23], '#005f5f'); + assert.equal(cm.colors.ansi[24], '#005f87'); + assert.equal(cm.colors.ansi[25], '#005faf'); + assert.equal(cm.colors.ansi[26], '#005fd7'); + assert.equal(cm.colors.ansi[27], '#005fff'); + assert.equal(cm.colors.ansi[28], '#008700'); + assert.equal(cm.colors.ansi[29], '#00875f'); + assert.equal(cm.colors.ansi[30], '#008787'); + assert.equal(cm.colors.ansi[31], '#0087af'); + assert.equal(cm.colors.ansi[32], '#0087d7'); + assert.equal(cm.colors.ansi[33], '#0087ff'); + assert.equal(cm.colors.ansi[34], '#00af00'); + assert.equal(cm.colors.ansi[35], '#00af5f'); + assert.equal(cm.colors.ansi[36], '#00af87'); + assert.equal(cm.colors.ansi[37], '#00afaf'); + assert.equal(cm.colors.ansi[38], '#00afd7'); + assert.equal(cm.colors.ansi[39], '#00afff'); + assert.equal(cm.colors.ansi[40], '#00d700'); + assert.equal(cm.colors.ansi[41], '#00d75f'); + assert.equal(cm.colors.ansi[42], '#00d787'); + assert.equal(cm.colors.ansi[43], '#00d7af'); + assert.equal(cm.colors.ansi[44], '#00d7d7'); + assert.equal(cm.colors.ansi[45], '#00d7ff'); + assert.equal(cm.colors.ansi[46], '#00ff00'); + assert.equal(cm.colors.ansi[47], '#00ff5f'); + assert.equal(cm.colors.ansi[48], '#00ff87'); + assert.equal(cm.colors.ansi[49], '#00ffaf'); + assert.equal(cm.colors.ansi[50], '#00ffd7'); + assert.equal(cm.colors.ansi[51], '#00ffff'); + assert.equal(cm.colors.ansi[52], '#5f0000'); + assert.equal(cm.colors.ansi[53], '#5f005f'); + assert.equal(cm.colors.ansi[54], '#5f0087'); + assert.equal(cm.colors.ansi[55], '#5f00af'); + assert.equal(cm.colors.ansi[56], '#5f00d7'); + assert.equal(cm.colors.ansi[57], '#5f00ff'); + assert.equal(cm.colors.ansi[58], '#5f5f00'); + assert.equal(cm.colors.ansi[59], '#5f5f5f'); + assert.equal(cm.colors.ansi[60], '#5f5f87'); + assert.equal(cm.colors.ansi[61], '#5f5faf'); + assert.equal(cm.colors.ansi[62], '#5f5fd7'); + assert.equal(cm.colors.ansi[63], '#5f5fff'); + assert.equal(cm.colors.ansi[64], '#5f8700'); + assert.equal(cm.colors.ansi[65], '#5f875f'); + assert.equal(cm.colors.ansi[66], '#5f8787'); + assert.equal(cm.colors.ansi[67], '#5f87af'); + assert.equal(cm.colors.ansi[68], '#5f87d7'); + assert.equal(cm.colors.ansi[69], '#5f87ff'); + assert.equal(cm.colors.ansi[70], '#5faf00'); + assert.equal(cm.colors.ansi[71], '#5faf5f'); + assert.equal(cm.colors.ansi[72], '#5faf87'); + assert.equal(cm.colors.ansi[73], '#5fafaf'); + assert.equal(cm.colors.ansi[74], '#5fafd7'); + assert.equal(cm.colors.ansi[75], '#5fafff'); + assert.equal(cm.colors.ansi[76], '#5fd700'); + assert.equal(cm.colors.ansi[77], '#5fd75f'); + assert.equal(cm.colors.ansi[78], '#5fd787'); + assert.equal(cm.colors.ansi[79], '#5fd7af'); + assert.equal(cm.colors.ansi[80], '#5fd7d7'); + assert.equal(cm.colors.ansi[81], '#5fd7ff'); + assert.equal(cm.colors.ansi[82], '#5fff00'); + assert.equal(cm.colors.ansi[83], '#5fff5f'); + assert.equal(cm.colors.ansi[84], '#5fff87'); + assert.equal(cm.colors.ansi[85], '#5fffaf'); + assert.equal(cm.colors.ansi[86], '#5fffd7'); + assert.equal(cm.colors.ansi[87], '#5fffff'); + assert.equal(cm.colors.ansi[88], '#870000'); + assert.equal(cm.colors.ansi[89], '#87005f'); + assert.equal(cm.colors.ansi[90], '#870087'); + assert.equal(cm.colors.ansi[91], '#8700af'); + assert.equal(cm.colors.ansi[92], '#8700d7'); + assert.equal(cm.colors.ansi[93], '#8700ff'); + assert.equal(cm.colors.ansi[94], '#875f00'); + assert.equal(cm.colors.ansi[95], '#875f5f'); + assert.equal(cm.colors.ansi[96], '#875f87'); + assert.equal(cm.colors.ansi[97], '#875faf'); + assert.equal(cm.colors.ansi[98], '#875fd7'); + assert.equal(cm.colors.ansi[99], '#875fff'); + assert.equal(cm.colors.ansi[100], '#878700'); + assert.equal(cm.colors.ansi[101], '#87875f'); + assert.equal(cm.colors.ansi[102], '#878787'); + assert.equal(cm.colors.ansi[103], '#8787af'); + assert.equal(cm.colors.ansi[104], '#8787d7'); + assert.equal(cm.colors.ansi[105], '#8787ff'); + assert.equal(cm.colors.ansi[106], '#87af00'); + assert.equal(cm.colors.ansi[107], '#87af5f'); + assert.equal(cm.colors.ansi[108], '#87af87'); + assert.equal(cm.colors.ansi[109], '#87afaf'); + assert.equal(cm.colors.ansi[110], '#87afd7'); + assert.equal(cm.colors.ansi[111], '#87afff'); + assert.equal(cm.colors.ansi[112], '#87d700'); + assert.equal(cm.colors.ansi[113], '#87d75f'); + assert.equal(cm.colors.ansi[114], '#87d787'); + assert.equal(cm.colors.ansi[115], '#87d7af'); + assert.equal(cm.colors.ansi[116], '#87d7d7'); + assert.equal(cm.colors.ansi[117], '#87d7ff'); + assert.equal(cm.colors.ansi[118], '#87ff00'); + assert.equal(cm.colors.ansi[119], '#87ff5f'); + assert.equal(cm.colors.ansi[120], '#87ff87'); + assert.equal(cm.colors.ansi[121], '#87ffaf'); + assert.equal(cm.colors.ansi[122], '#87ffd7'); + assert.equal(cm.colors.ansi[123], '#87ffff'); + assert.equal(cm.colors.ansi[124], '#af0000'); + assert.equal(cm.colors.ansi[125], '#af005f'); + assert.equal(cm.colors.ansi[126], '#af0087'); + assert.equal(cm.colors.ansi[127], '#af00af'); + assert.equal(cm.colors.ansi[128], '#af00d7'); + assert.equal(cm.colors.ansi[129], '#af00ff'); + assert.equal(cm.colors.ansi[130], '#af5f00'); + assert.equal(cm.colors.ansi[131], '#af5f5f'); + assert.equal(cm.colors.ansi[132], '#af5f87'); + assert.equal(cm.colors.ansi[133], '#af5faf'); + assert.equal(cm.colors.ansi[134], '#af5fd7'); + assert.equal(cm.colors.ansi[135], '#af5fff'); + assert.equal(cm.colors.ansi[136], '#af8700'); + assert.equal(cm.colors.ansi[137], '#af875f'); + assert.equal(cm.colors.ansi[138], '#af8787'); + assert.equal(cm.colors.ansi[139], '#af87af'); + assert.equal(cm.colors.ansi[140], '#af87d7'); + assert.equal(cm.colors.ansi[141], '#af87ff'); + assert.equal(cm.colors.ansi[142], '#afaf00'); + assert.equal(cm.colors.ansi[143], '#afaf5f'); + assert.equal(cm.colors.ansi[144], '#afaf87'); + assert.equal(cm.colors.ansi[145], '#afafaf'); + assert.equal(cm.colors.ansi[146], '#afafd7'); + assert.equal(cm.colors.ansi[147], '#afafff'); + assert.equal(cm.colors.ansi[148], '#afd700'); + assert.equal(cm.colors.ansi[149], '#afd75f'); + assert.equal(cm.colors.ansi[150], '#afd787'); + assert.equal(cm.colors.ansi[151], '#afd7af'); + assert.equal(cm.colors.ansi[152], '#afd7d7'); + assert.equal(cm.colors.ansi[153], '#afd7ff'); + assert.equal(cm.colors.ansi[154], '#afff00'); + assert.equal(cm.colors.ansi[155], '#afff5f'); + assert.equal(cm.colors.ansi[156], '#afff87'); + assert.equal(cm.colors.ansi[157], '#afffaf'); + assert.equal(cm.colors.ansi[158], '#afffd7'); + assert.equal(cm.colors.ansi[159], '#afffff'); + assert.equal(cm.colors.ansi[160], '#d70000'); + assert.equal(cm.colors.ansi[161], '#d7005f'); + assert.equal(cm.colors.ansi[162], '#d70087'); + assert.equal(cm.colors.ansi[163], '#d700af'); + assert.equal(cm.colors.ansi[164], '#d700d7'); + assert.equal(cm.colors.ansi[165], '#d700ff'); + assert.equal(cm.colors.ansi[166], '#d75f00'); + assert.equal(cm.colors.ansi[167], '#d75f5f'); + assert.equal(cm.colors.ansi[168], '#d75f87'); + assert.equal(cm.colors.ansi[169], '#d75faf'); + assert.equal(cm.colors.ansi[170], '#d75fd7'); + assert.equal(cm.colors.ansi[171], '#d75fff'); + assert.equal(cm.colors.ansi[172], '#d78700'); + assert.equal(cm.colors.ansi[173], '#d7875f'); + assert.equal(cm.colors.ansi[174], '#d78787'); + assert.equal(cm.colors.ansi[175], '#d787af'); + assert.equal(cm.colors.ansi[176], '#d787d7'); + assert.equal(cm.colors.ansi[177], '#d787ff'); + assert.equal(cm.colors.ansi[178], '#d7af00'); + assert.equal(cm.colors.ansi[179], '#d7af5f'); + assert.equal(cm.colors.ansi[180], '#d7af87'); + assert.equal(cm.colors.ansi[181], '#d7afaf'); + assert.equal(cm.colors.ansi[182], '#d7afd7'); + assert.equal(cm.colors.ansi[183], '#d7afff'); + assert.equal(cm.colors.ansi[184], '#d7d700'); + assert.equal(cm.colors.ansi[185], '#d7d75f'); + assert.equal(cm.colors.ansi[186], '#d7d787'); + assert.equal(cm.colors.ansi[187], '#d7d7af'); + assert.equal(cm.colors.ansi[188], '#d7d7d7'); + assert.equal(cm.colors.ansi[189], '#d7d7ff'); + assert.equal(cm.colors.ansi[190], '#d7ff00'); + assert.equal(cm.colors.ansi[191], '#d7ff5f'); + assert.equal(cm.colors.ansi[192], '#d7ff87'); + assert.equal(cm.colors.ansi[193], '#d7ffaf'); + assert.equal(cm.colors.ansi[194], '#d7ffd7'); + assert.equal(cm.colors.ansi[195], '#d7ffff'); + assert.equal(cm.colors.ansi[196], '#ff0000'); + assert.equal(cm.colors.ansi[197], '#ff005f'); + assert.equal(cm.colors.ansi[198], '#ff0087'); + assert.equal(cm.colors.ansi[199], '#ff00af'); + assert.equal(cm.colors.ansi[200], '#ff00d7'); + assert.equal(cm.colors.ansi[201], '#ff00ff'); + assert.equal(cm.colors.ansi[202], '#ff5f00'); + assert.equal(cm.colors.ansi[203], '#ff5f5f'); + assert.equal(cm.colors.ansi[204], '#ff5f87'); + assert.equal(cm.colors.ansi[205], '#ff5faf'); + assert.equal(cm.colors.ansi[206], '#ff5fd7'); + assert.equal(cm.colors.ansi[207], '#ff5fff'); + assert.equal(cm.colors.ansi[208], '#ff8700'); + assert.equal(cm.colors.ansi[209], '#ff875f'); + assert.equal(cm.colors.ansi[210], '#ff8787'); + assert.equal(cm.colors.ansi[211], '#ff87af'); + assert.equal(cm.colors.ansi[212], '#ff87d7'); + assert.equal(cm.colors.ansi[213], '#ff87ff'); + assert.equal(cm.colors.ansi[214], '#ffaf00'); + assert.equal(cm.colors.ansi[215], '#ffaf5f'); + assert.equal(cm.colors.ansi[216], '#ffaf87'); + assert.equal(cm.colors.ansi[217], '#ffafaf'); + assert.equal(cm.colors.ansi[218], '#ffafd7'); + assert.equal(cm.colors.ansi[219], '#ffafff'); + assert.equal(cm.colors.ansi[220], '#ffd700'); + assert.equal(cm.colors.ansi[221], '#ffd75f'); + assert.equal(cm.colors.ansi[222], '#ffd787'); + assert.equal(cm.colors.ansi[223], '#ffd7af'); + assert.equal(cm.colors.ansi[224], '#ffd7d7'); + assert.equal(cm.colors.ansi[225], '#ffd7ff'); + assert.equal(cm.colors.ansi[226], '#ffff00'); + assert.equal(cm.colors.ansi[227], '#ffff5f'); + assert.equal(cm.colors.ansi[228], '#ffff87'); + assert.equal(cm.colors.ansi[229], '#ffffaf'); + assert.equal(cm.colors.ansi[230], '#ffffd7'); + assert.equal(cm.colors.ansi[231], '#ffffff'); + assert.equal(cm.colors.ansi[232], '#080808'); + assert.equal(cm.colors.ansi[233], '#121212'); + assert.equal(cm.colors.ansi[234], '#1c1c1c'); + assert.equal(cm.colors.ansi[235], '#262626'); + assert.equal(cm.colors.ansi[236], '#303030'); + assert.equal(cm.colors.ansi[237], '#3a3a3a'); + assert.equal(cm.colors.ansi[238], '#444444'); + assert.equal(cm.colors.ansi[239], '#4e4e4e'); + assert.equal(cm.colors.ansi[240], '#585858'); + assert.equal(cm.colors.ansi[241], '#626262'); + assert.equal(cm.colors.ansi[242], '#6c6c6c'); + assert.equal(cm.colors.ansi[243], '#767676'); + assert.equal(cm.colors.ansi[244], '#808080'); + assert.equal(cm.colors.ansi[245], '#8a8a8a'); + assert.equal(cm.colors.ansi[246], '#949494'); + assert.equal(cm.colors.ansi[247], '#9e9e9e'); + assert.equal(cm.colors.ansi[248], '#a8a8a8'); + assert.equal(cm.colors.ansi[249], '#b2b2b2'); + assert.equal(cm.colors.ansi[250], '#bcbcbc'); + assert.equal(cm.colors.ansi[251], '#c6c6c6'); + assert.equal(cm.colors.ansi[252], '#d0d0d0'); + assert.equal(cm.colors.ansi[253], '#dadada'); + assert.equal(cm.colors.ansi[254], '#e4e4e4'); + assert.equal(cm.colors.ansi[255], '#eeeeee'); + }); + }); + + describe('setTheme', () => { + it('should not throw when not setting all colors', () => { + assert.doesNotThrow(() => { + cm.setTheme({}); + }); + }); + + it('should set a partial set of colors, using the default if not present', () => { + assert.equal(cm.colors.background, '#000000'); + assert.equal(cm.colors.foreground, '#ffffff'); + cm.setTheme({ + background: '#FF0000', + foreground: '#00FF00' + }); + assert.equal(cm.colors.background, '#FF0000'); + assert.equal(cm.colors.foreground, '#00FF00'); + cm.setTheme({ + background: '#0000FF' + }); + assert.equal(cm.colors.background, '#0000FF'); + // FG reverts back to default + assert.equal(cm.colors.foreground, '#ffffff'); + }); + }); +}); diff --git a/xterm.js/src/renderer/ColorManager.ts b/xterm.js/src/renderer/ColorManager.ts new file mode 100644 index 0000000..ea5f1cb --- /dev/null +++ b/xterm.js/src/renderer/ColorManager.ts @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { IColorSet, IColorManager } from './Interfaces'; +import { ITheme } from '../Interfaces'; + +const DEFAULT_FOREGROUND = '#ffffff'; +const DEFAULT_BACKGROUND = '#000000'; +const DEFAULT_CURSOR = '#ffffff'; +const DEFAULT_CURSOR_ACCENT = '#000000'; +const DEFAULT_SELECTION = 'rgba(255, 255, 255, 0.3)'; +export const DEFAULT_ANSI_COLORS = [ + // dark: + '#2e3436', + '#cc0000', + '#4e9a06', + '#c4a000', + '#3465a4', + '#75507b', + '#06989a', + '#d3d7cf', + // bright: + '#555753', + '#ef2929', + '#8ae234', + '#fce94f', + '#729fcf', + '#ad7fa8', + '#34e2e2', + '#eeeeec' +]; + +/** + * Fills an existing 16 length string with the remaining 240 ANSI colors. + * @param first16Colors The first 16 ANSI colors. + */ +function generate256Colors(first16Colors: string[]): string[] { + let colors = first16Colors.slice(); + + // Generate colors (16-231) + let v = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]; + for (let i = 0; i < 216; i++) { + const r = toPaddedHex(v[(i / 36) % 6 | 0]); + const g = toPaddedHex(v[(i / 6) % 6 | 0]); + const b = toPaddedHex(v[i % 6]); + colors.push(`#${r}${g}${b}`); + } + + // Generate greys (232-255) + for (let i = 0; i < 24; i++) { + const c = toPaddedHex(8 + i * 10); + colors.push(`#${c}${c}${c}`); + } + + return colors; +} + +function toPaddedHex(c: number): string { + let s = c.toString(16); + return s.length < 2 ? '0' + s : s; +} + +/** + * Manages the source of truth for a terminal's colors. + */ +export class ColorManager implements IColorManager { + public colors: IColorSet; + + constructor() { + this.colors = { + foreground: DEFAULT_FOREGROUND, + background: DEFAULT_BACKGROUND, + cursor: DEFAULT_CURSOR, + cursorAccent: DEFAULT_CURSOR_ACCENT, + selection: DEFAULT_SELECTION, + ansi: generate256Colors(DEFAULT_ANSI_COLORS) + }; + } + + /** + * Sets the terminal's theme. + * @param theme The theme to use. If a partial theme is provided then default + * colors will be used where colors are not defined. + */ + public setTheme(theme: ITheme): void { + this.colors.foreground = theme.foreground || DEFAULT_FOREGROUND; + this.colors.background = theme.background || DEFAULT_BACKGROUND; + this.colors.cursor = theme.cursor || DEFAULT_CURSOR; + this.colors.cursorAccent = theme.cursorAccent || DEFAULT_CURSOR_ACCENT; + this.colors.selection = theme.selection || DEFAULT_SELECTION; + this.colors.ansi[0] = theme.black || DEFAULT_ANSI_COLORS[0]; + this.colors.ansi[1] = theme.red || DEFAULT_ANSI_COLORS[1]; + this.colors.ansi[2] = theme.green || DEFAULT_ANSI_COLORS[2]; + this.colors.ansi[3] = theme.yellow || DEFAULT_ANSI_COLORS[3]; + this.colors.ansi[4] = theme.blue || DEFAULT_ANSI_COLORS[4]; + this.colors.ansi[5] = theme.magenta || DEFAULT_ANSI_COLORS[5]; + this.colors.ansi[6] = theme.cyan || DEFAULT_ANSI_COLORS[6]; + this.colors.ansi[7] = theme.white || DEFAULT_ANSI_COLORS[7]; + this.colors.ansi[8] = theme.brightBlack || DEFAULT_ANSI_COLORS[8]; + this.colors.ansi[9] = theme.brightRed || DEFAULT_ANSI_COLORS[9]; + this.colors.ansi[10] = theme.brightGreen || DEFAULT_ANSI_COLORS[10]; + this.colors.ansi[11] = theme.brightYellow || DEFAULT_ANSI_COLORS[11]; + this.colors.ansi[12] = theme.brightBlue || DEFAULT_ANSI_COLORS[12]; + this.colors.ansi[13] = theme.brightMagenta || DEFAULT_ANSI_COLORS[13]; + this.colors.ansi[14] = theme.brightCyan || DEFAULT_ANSI_COLORS[14]; + this.colors.ansi[15] = theme.brightWhite || DEFAULT_ANSI_COLORS[15]; + } +} diff --git a/xterm.js/src/renderer/CursorRenderLayer.ts b/xterm.js/src/renderer/CursorRenderLayer.ts new file mode 100644 index 0000000..689d691 --- /dev/null +++ b/xterm.js/src/renderer/CursorRenderLayer.ts @@ -0,0 +1,354 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { IColorSet, IRenderDimensions } from './Interfaces'; +import { IBuffer, ICharMeasure, ITerminal, ITerminalOptions } from '../Interfaces'; +import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer'; +import { GridCache } from './GridCache'; +import { FLAGS } from './Types'; +import { BaseRenderLayer } from './BaseRenderLayer'; +import { CharData } from '../Types'; + +interface CursorState { + x: number; + y: number; + isFocused: boolean; + style: string; + width: number; +} + +/** + * The time between cursor blinks. + */ +const BLINK_INTERVAL = 600; + +export class CursorRenderLayer extends BaseRenderLayer { + private _state: CursorState; + private _cursorRenderers: {[key: string]: (terminal: ITerminal, x: number, y: number, charData: CharData) => void}; + private _cursorBlinkStateManager: CursorBlinkStateManager; + private _isFocused: boolean; + + constructor(container: HTMLElement, zIndex: number, colors: IColorSet) { + super(container, 'cursor', zIndex, true, colors); + this._state = { + x: null, + y: null, + isFocused: null, + style: null, + width: null, + }; + this._cursorRenderers = { + 'bar': this._renderBarCursor.bind(this), + 'block': this._renderBlockCursor.bind(this), + 'underline': this._renderUnderlineCursor.bind(this) + }; + // TODO: Consider initial options? Maybe onOptionsChanged should be called at the end of open? + } + + public resize(terminal: ITerminal, dim: IRenderDimensions, charSizeChanged: boolean): void { + super.resize(terminal, dim, charSizeChanged); + // Resizing the canvas discards the contents of the canvas so clear state + this._state = { + x: null, + y: null, + isFocused: null, + style: null, + width: null, + }; + } + + public reset(terminal: ITerminal): void { + this._clearCursor(); + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.dispose(); + this._cursorBlinkStateManager = null; + this.onOptionsChanged(terminal); + } + } + + public onBlur(terminal: ITerminal): void { + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.pause(); + } + terminal.refresh(terminal.buffer.y, terminal.buffer.y); + } + + public onFocus(terminal: ITerminal): void { + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.resume(terminal); + } else { + terminal.refresh(terminal.buffer.y, terminal.buffer.y); + } + } + + public onOptionsChanged(terminal: ITerminal): void { + if (terminal.options.cursorBlink) { + if (!this._cursorBlinkStateManager) { + this._cursorBlinkStateManager = new CursorBlinkStateManager(terminal, () => { + this._render(terminal, true); + }); + } + } else { + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.dispose(); + this._cursorBlinkStateManager = null; + } + // Request a refresh from the terminal as management of rendering is being + // moved back to the terminal + terminal.refresh(terminal.buffer.y, terminal.buffer.y); + } + } + + public onCursorMove(terminal: ITerminal): void { + if (this._cursorBlinkStateManager) { + this._cursorBlinkStateManager.restartBlinkAnimation(terminal); + } + } + + public onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void { + // Only render if the animation frame is not active + if (!this._cursorBlinkStateManager || this._cursorBlinkStateManager.isPaused) { + this._render(terminal, false); + } + } + + private _render(terminal: ITerminal, triggeredByAnimationFrame: boolean): void { + // Don't draw the cursor if it's hidden + if (!terminal.cursorState || terminal.cursorHidden) { + this._clearCursor(); + return; + } + + const cursorY = terminal.buffer.ybase + terminal.buffer.y; + const viewportRelativeCursorY = cursorY - terminal.buffer.ydisp; + + // Don't draw the cursor if it's off-screen + if (viewportRelativeCursorY < 0 || viewportRelativeCursorY >= terminal.rows) { + this._clearCursor(); + return; + } + + const charData = terminal.buffer.lines.get(cursorY)[terminal.buffer.x]; + if (!charData) { + return; + } + + if (!terminal.isFocused) { + this._clearCursor(); + this._ctx.save(); + this._ctx.fillStyle = this._colors.cursor; + this._renderBlurCursor(terminal, terminal.buffer.x, viewportRelativeCursorY, charData); + this._ctx.restore(); + this._state.x = terminal.buffer.x; + this._state.y = viewportRelativeCursorY; + this._state.isFocused = false; + this._state.style = terminal.options.cursorStyle; + this._state.width = charData[CHAR_DATA_WIDTH_INDEX]; + return; + } + + // Don't draw the cursor if it's blinking + if (this._cursorBlinkStateManager && !this._cursorBlinkStateManager.isCursorVisible) { + this._clearCursor(); + return; + } + + if (this._state) { + // The cursor is already in the correct spot, don't redraw + if (this._state.x === terminal.buffer.x && + this._state.y === viewportRelativeCursorY && + this._state.isFocused === terminal.isFocused && + this._state.style === terminal.options.cursorStyle && + this._state.width === charData[CHAR_DATA_WIDTH_INDEX]) { + return; + } + this._clearCursor(); + } + + this._ctx.save(); + this._cursorRenderers[terminal.options.cursorStyle || 'block'](terminal, terminal.buffer.x, viewportRelativeCursorY, charData); + this._ctx.restore(); + + this._state.x = terminal.buffer.x; + this._state.y = viewportRelativeCursorY; + this._state.isFocused = false; + this._state.style = terminal.options.cursorStyle; + this._state.width = charData[CHAR_DATA_WIDTH_INDEX]; + } + + private _clearCursor(): void { + if (this._state) { + this.clearCells(this._state.x, this._state.y, this._state.width, 1); + this._state = { + x: null, + y: null, + isFocused: null, + style: null, + width: null, + }; + } + } + + private _renderBarCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void { + this._ctx.save(); + this._ctx.fillStyle = this._colors.cursor; + this.fillLeftLineAtCell(x, y); + this._ctx.restore(); + } + + private _renderBlockCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void { + this._ctx.save(); + this._ctx.fillStyle = this._colors.cursor; + this.fillCells(x, y, charData[CHAR_DATA_WIDTH_INDEX], 1); + this._ctx.fillStyle = this._colors.cursorAccent; + this.fillCharTrueColor(terminal, charData, x, y); + this._ctx.restore(); + } + + private _renderUnderlineCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void { + this._ctx.save(); + this._ctx.fillStyle = this._colors.cursor; + this.fillBottomLineAtCells(x, y); + this._ctx.restore(); + } + + private _renderBlurCursor(terminal: ITerminal, x: number, y: number, charData: CharData): void { + this._ctx.save(); + this._ctx.strokeStyle = this._colors.cursor; + this.strokeRectAtCell(x, y, charData[CHAR_DATA_WIDTH_INDEX], 1); + this._ctx.restore(); + } +} + +class CursorBlinkStateManager { + public isCursorVisible: boolean; + + private _animationFrame: number; + private _blinkStartTimeout: number; + private _blinkInterval: number; + + /** + * The time at which the animation frame was restarted, this is used on the + * next render to restart the timers so they don't need to restart the timers + * multiple times over a short period. + */ + private _animationTimeRestarted: number; + + constructor( + terminal: ITerminal, + private renderCallback: () => void + ) { + this.isCursorVisible = true; + if (terminal.isFocused) { + this._restartInterval(); + } + } + + public get isPaused(): boolean { return !(this._blinkStartTimeout || this._blinkInterval); } + + public dispose(): void { + if (this._blinkInterval) { + window.clearInterval(this._blinkInterval); + this._blinkInterval = null; + } + if (this._blinkStartTimeout) { + window.clearTimeout(this._blinkStartTimeout); + this._blinkStartTimeout = null; + } + if (this._animationFrame) { + window.cancelAnimationFrame(this._animationFrame); + this._animationFrame = null; + } + } + + public restartBlinkAnimation(terminal: ITerminal): void { + if (this.isPaused) { + return; + } + // Save a timestamp so that the restart can be done on the next interval + this._animationTimeRestarted = Date.now(); + // Force a cursor render to ensure it's visible and in the correct position + this.isCursorVisible = true; + if (!this._animationFrame) { + this._animationFrame = window.requestAnimationFrame(() => { + this.renderCallback(); + this._animationFrame = null; + }); + } + } + + private _restartInterval(timeToStart: number = BLINK_INTERVAL): void { + // Clear any existing interval + if (this._blinkInterval) { + window.clearInterval(this._blinkInterval); + } + + // Setup the initial timeout which will hide the cursor, this is done before + // the regular interval is setup in order to support restarting the blink + // animation in a lightweight way (without thrashing clearInterval and + // setInterval). + this._blinkStartTimeout = setTimeout(() => { + // Check if another animation restart was requested while this was being + // started + if (this._animationTimeRestarted) { + const time = BLINK_INTERVAL - (Date.now() - this._animationTimeRestarted); + this._animationTimeRestarted = null; + if (time > 0) { + this._restartInterval(time); + return; + } + } + + // Hide the cursor + this.isCursorVisible = false; + this._animationFrame = window.requestAnimationFrame(() => { + this.renderCallback(); + this._animationFrame = null; + }); + + // Setup the blink interval + this._blinkInterval = setInterval(() => { + // Adjust the animation time if it was restarted + if (this._animationTimeRestarted) { + // calc time diff + // Make restart interval do a setTimeout initially? + const time = BLINK_INTERVAL - (Date.now() - this._animationTimeRestarted); + this._animationTimeRestarted = null; + this._restartInterval(time); + return; + } + + // Invert visibility and render + this.isCursorVisible = !this.isCursorVisible; + this._animationFrame = window.requestAnimationFrame(() => { + this.renderCallback(); + this._animationFrame = null; + }); + }, BLINK_INTERVAL); + }, timeToStart); + } + + public pause(): void { + this.isCursorVisible = true; + if (this._blinkInterval) { + window.clearInterval(this._blinkInterval); + this._blinkInterval = null; + } + if (this._blinkStartTimeout) { + window.clearTimeout(this._blinkStartTimeout); + this._blinkStartTimeout = null; + } + if (this._animationFrame) { + window.cancelAnimationFrame(this._animationFrame); + this._animationFrame = null; + } + } + + public resume(terminal: ITerminal): void { + this._animationTimeRestarted = null; + this._restartInterval(); + this.restartBlinkAnimation(terminal); + } +} diff --git a/xterm.js/src/renderer/GridCache.test.ts b/xterm.js/src/renderer/GridCache.test.ts new file mode 100644 index 0000000..c4b1c22 --- /dev/null +++ b/xterm.js/src/renderer/GridCache.test.ts @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert } from 'chai'; +import { GridCache } from './GridCache'; + +describe('GridCache', () => { + let grid: GridCache; + + beforeEach(() => { + grid = new GridCache(); + }); + + describe('constructor', () => { + it('should create an empty cache', () => { + assert.equal(grid.cache.length, 0); + }); + }); + + describe('resize', () => { + it('should fill all new elements with null', () => { + grid.resize(2, 2); + assert.equal(grid.cache.length, 2); + assert.equal(grid.cache[0].length, 2); + assert.equal(grid.cache[0][0], null); + assert.equal(grid.cache[0][1], null); + assert.equal(grid.cache[1].length, 2); + assert.equal(grid.cache[1][0], null); + assert.equal(grid.cache[1][1], null); + grid.resize(3, 2); + assert.equal(grid.cache.length, 3); + assert.equal(grid.cache[2][0], null); + assert.equal(grid.cache[2][1], null); + }); + + it('should remove rows/cols from the cache when reduced', () => { + grid.resize(2, 2); + grid.resize(1, 1); + assert.equal(grid.cache.length, 1); + assert.equal(grid.cache[0].length, 1); + }); + + it('should not touch existing cache entries if they fit in the new cache', () => { + grid.resize(1, 1); + assert.equal(grid.cache[0][0], null); + grid.cache[0][0] = 1; + grid.resize(2, 1); + assert.equal(grid.cache[0][0], 1); + }); + }); + + describe('clear', () => { + it('should make all entries null', () => { + grid.resize(1, 1); + grid.cache[0][0] = 1; + grid.clear(); + assert.equal(grid.cache[0][0], null); + }); + }); +}); diff --git a/xterm.js/src/renderer/GridCache.ts b/xterm.js/src/renderer/GridCache.ts new file mode 100644 index 0000000..dd188c6 --- /dev/null +++ b/xterm.js/src/renderer/GridCache.ts @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +export class GridCache { + public cache: T[][]; + + public constructor() { + this.cache = []; + } + + public resize(width: number, height: number): void { + for (let x = 0; x < width; x++) { + if (this.cache.length <= x) { + this.cache.push([]); + } + for (let y = this.cache[x].length; y < height; y++) { + this.cache[x].push(null); + } + this.cache[x].length = height; + } + this.cache.length = width; + } + + public clear(): void { + for (let x = 0; x < this.cache.length; x++) { + for (let y = 0; y < this.cache[x].length; y++) { + this.cache[x][y] = null; + } + } + } +} diff --git a/xterm.js/src/renderer/Interfaces.ts b/xterm.js/src/renderer/Interfaces.ts new file mode 100644 index 0000000..be1b39d --- /dev/null +++ b/xterm.js/src/renderer/Interfaces.ts @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ITerminal, ITerminalOptions, ITheme, IEventEmitter } from '../Interfaces'; + +export interface IRenderer extends IEventEmitter { + dimensions: IRenderDimensions; + colorManager: IColorManager; + + setTheme(theme: ITheme): IColorSet; + onWindowResize(devicePixelRatio: number): void; + onResize(cols: number, rows: number, didCharSizeChange: boolean): void; + onCharSizeChanged(): void; + onBlur(): void; + onFocus(): void; + onSelectionChanged(start: [number, number], end: [number, number]): void; + onCursorMove(): void; + onOptionsChanged(): void; + clear(): void; + queueRefresh(start: number, end: number): void; +} + +export interface IRenderLayer { + /** + * Called when the terminal loses focus. + */ + onBlur(terminal: ITerminal): void; + + /** + * * Called when the terminal gets focus. + */ + onFocus(terminal: ITerminal): void; + + /** + * Called when the cursor is moved. + */ + onCursorMove(terminal: ITerminal): void; + + /** + * Called when options change. + */ + onOptionsChanged(terminal: ITerminal): void; + + /** + * Called when the theme changes. + */ + onThemeChanged(terminal: ITerminal, colorSet: IColorSet): void; + + /** + * Called when the data in the grid has changed (or needs to be rendered + * again). + */ + onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void; + + /** + * Calls when the selection changes. + */ + onSelectionChanged(terminal: ITerminal, start: [number, number], end: [number, number]): void; + + /** + * Resize the render layer. + */ + resize(terminal: ITerminal, dim: IRenderDimensions, charSizeChanged: boolean): void; + + /** + * Clear the state of the render layer. + */ + reset(terminal: ITerminal): void; +} + +export interface IColorManager { + colors: IColorSet; +} + +export interface IColorSet { + foreground: string; + background: string; + cursor: string; + cursorAccent: string; + selection: string; + ansi: string[]; +} + +export interface IRenderDimensions { + scaledCharWidth: number; + scaledCharHeight: number; + scaledCellWidth: number; + scaledCellHeight: number; + scaledCharLeft: number; + scaledCharTop: number; + scaledCanvasWidth: number; + scaledCanvasHeight: number; + canvasWidth: number; + canvasHeight: number; + actualCellWidth: number; + actualCellHeight: number; +} diff --git a/xterm.js/src/renderer/LinkRenderLayer.ts b/xterm.js/src/renderer/LinkRenderLayer.ts new file mode 100644 index 0000000..8f3b63a --- /dev/null +++ b/xterm.js/src/renderer/LinkRenderLayer.ts @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { IColorSet, IRenderDimensions } from './Interfaces'; +import { IBuffer, ICharMeasure, ITerminal, ILinkifierAccessor } from '../Interfaces'; +import { CHAR_DATA_ATTR_INDEX } from '../Buffer'; +import { GridCache } from './GridCache'; +import { FLAGS } from './Types'; +import { BaseRenderLayer, INVERTED_DEFAULT_COLOR } from './BaseRenderLayer'; +import { LinkHoverEvent, LinkHoverEventTypes } from '../Types'; + +export class LinkRenderLayer extends BaseRenderLayer { + private _state: LinkHoverEvent = null; + + constructor(container: HTMLElement, zIndex: number, colors: IColorSet, terminal: ILinkifierAccessor) { + super(container, 'link', zIndex, true, colors); + terminal.linkifier.on(LinkHoverEventTypes.HOVER, (e: LinkHoverEvent) => this._onLinkHover(e)); + terminal.linkifier.on(LinkHoverEventTypes.LEAVE, (e: LinkHoverEvent) => this._onLinkLeave(e)); + } + + public resize(terminal: ITerminal, dim: IRenderDimensions, charSizeChanged: boolean): void { + super.resize(terminal, dim, charSizeChanged); + // Resizing the canvas discards the contents of the canvas so clear state + this._state = null; + } + + public reset(terminal: ITerminal): void { + this._clearCurrentLink(); + } + + private _clearCurrentLink(): void { + if (this._state) { + this.clearCells(this._state.x, this._state.y, this._state.length, 1); + this._state = null; + } + } + + private _onLinkHover(e: LinkHoverEvent): void { + this._ctx.fillStyle = this._colors.foreground; + this.fillBottomLineAtCells(e.x, e.y, e.length); + this._state = e; + } + + private _onLinkLeave(e: LinkHoverEvent): void { + this._clearCurrentLink(); + } +} diff --git a/xterm.js/src/renderer/Renderer.ts b/xterm.js/src/renderer/Renderer.ts new file mode 100644 index 0000000..6ba7b40 --- /dev/null +++ b/xterm.js/src/renderer/Renderer.ts @@ -0,0 +1,276 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ITerminal, ITheme } from '../Interfaces'; +import { CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from '../Buffer'; +import { TextRenderLayer } from './TextRenderLayer'; +import { SelectionRenderLayer } from './SelectionRenderLayer'; +import { CursorRenderLayer } from './CursorRenderLayer'; +import { ColorManager } from './ColorManager'; +import { BaseRenderLayer } from './BaseRenderLayer'; +import { IRenderLayer, IColorSet, IRenderer, IRenderDimensions } from './Interfaces'; +import { LinkRenderLayer } from './LinkRenderLayer'; +import { EventEmitter } from '../EventEmitter'; +import { ScreenDprMonitor } from '../utils/ScreenDprMonitor'; + +export class Renderer extends EventEmitter implements IRenderer { + /** A queue of the rows to be refreshed */ + private _refreshRowsQueue: {start: number, end: number}[] = []; + private _refreshAnimationFrame = null; + + private _renderLayers: IRenderLayer[]; + private _devicePixelRatio: number; + private _screenDprMonitor: ScreenDprMonitor; + private _isPaused: boolean = false; + private _needsFullRefresh: boolean = false; + + public colorManager: ColorManager; + public dimensions: IRenderDimensions; + + constructor(private _terminal: ITerminal, theme: ITheme) { + super(); + this.colorManager = new ColorManager(); + if (theme) { + this.colorManager.setTheme(theme); + } + + this._renderLayers = [ + new TextRenderLayer(this._terminal.element, 0, this.colorManager.colors, + this._terminal.options.allowTransparency), + new SelectionRenderLayer(this._terminal.element, 1, this.colorManager.colors), + new LinkRenderLayer(this._terminal.element, 2, this.colorManager.colors, this._terminal), + new CursorRenderLayer(this._terminal.element, 3, this.colorManager.colors) + ]; + this.dimensions = { + scaledCharWidth: null, + scaledCharHeight: null, + scaledCellWidth: null, + scaledCellHeight: null, + scaledCharLeft: null, + scaledCharTop: null, + scaledCanvasWidth: null, + scaledCanvasHeight: null, + canvasWidth: null, + canvasHeight: null, + actualCellWidth: null, + actualCellHeight: null + }; + this._devicePixelRatio = window.devicePixelRatio; + this._updateDimensions(); + + this._screenDprMonitor = new ScreenDprMonitor(); + this._screenDprMonitor.setListener(() => this.onWindowResize(window.devicePixelRatio)); + + // Detect whether IntersectionObserver is detected and enable renderer pause + // and resume based on terminal visibility if so + if ('IntersectionObserver' in window) { + const observer = new IntersectionObserver(e => this.onIntersectionChange(e[0]), {threshold: 0}); + observer.observe(this._terminal.element); + } + } + + public onIntersectionChange(entry: IntersectionObserverEntry): void { + this._isPaused = entry.intersectionRatio === 0; + if (!this._isPaused && this._needsFullRefresh) { + this._terminal.refresh(0, this._terminal.rows - 1); + } + } + + public onWindowResize(devicePixelRatio: number): void { + // If the device pixel ratio changed, the char atlas needs to be regenerated + // and the terminal needs to refreshed + if (this._devicePixelRatio !== devicePixelRatio) { + this._devicePixelRatio = devicePixelRatio; + this.onResize(this._terminal.cols, this._terminal.rows, true); + } + } + + public setTheme(theme: ITheme): IColorSet { + this.colorManager.setTheme(theme); + + // Clear layers and force a full render + this._renderLayers.forEach(l => { + l.onThemeChanged(this._terminal, this.colorManager.colors); + l.reset(this._terminal); + }); + + if (this._isPaused) { + this._needsFullRefresh = true; + } else { + this._terminal.refresh(0, this._terminal.rows - 1); + } + + return this.colorManager.colors; + } + + public onResize(cols: number, rows: number, didCharSizeChange: boolean): void { + // Update character and canvas dimensions + this._updateDimensions(); + + // Resize all render layers + this._renderLayers.forEach(l => l.resize(this._terminal, this.dimensions, didCharSizeChange)); + + // Force a refresh + if (this._isPaused) { + this._needsFullRefresh = true; + } else { + this._terminal.refresh(0, this._terminal.rows - 1); + } + + this.emit('resize', { + width: this.dimensions.canvasWidth, + height: this.dimensions.canvasHeight + }); + } + + public onCharSizeChanged(): void { + this.onResize(this._terminal.cols, this._terminal.rows, true); + } + + public onBlur(): void { + this._runOperation(l => l.onBlur(this._terminal)); + } + + public onFocus(): void { + this._runOperation(l => l.onFocus(this._terminal)); + } + + public onSelectionChanged(start: [number, number], end: [number, number]): void { + this._runOperation(l => l.onSelectionChanged(this._terminal, start, end)); + } + + public onCursorMove(): void { + this._runOperation(l => l.onCursorMove(this._terminal)); + } + + public onOptionsChanged(): void { + this._runOperation(l => l.onOptionsChanged(this._terminal)); + } + + public clear(): void { + this._runOperation(l => l.reset(this._terminal)); + } + + private _runOperation(operation: (layer: IRenderLayer) => void): void { + if (this._isPaused) { + this._needsFullRefresh = true; + } else { + this._renderLayers.forEach(l => operation(l)); + } + } + + /** + * Queues a refresh between two rows (inclusive), to be done on next animation + * frame. + * @param {number} start The start row. + * @param {number} end The end row. + */ + public queueRefresh(start: number, end: number): void { + if (this._isPaused) { + this._needsFullRefresh = true; + return; + } + this._refreshRowsQueue.push({ start: start, end: end }); + if (!this._refreshAnimationFrame) { + this._refreshAnimationFrame = window.requestAnimationFrame(this._refreshLoop.bind(this)); + } + } + + /** + * Performs the refresh loop callback, calling refresh only if a refresh is + * necessary before queueing up the next one. + */ + private _refreshLoop(): void { + let start; + let end; + if (this._refreshRowsQueue.length > 4) { + // Just do a full refresh when 5+ refreshes are queued + start = 0; + end = this._terminal.rows - 1; + } else { + // Get start and end rows that need refreshing + start = this._refreshRowsQueue[0].start; + end = this._refreshRowsQueue[0].end; + for (let i = 1; i < this._refreshRowsQueue.length; i++) { + if (this._refreshRowsQueue[i].start < start) { + start = this._refreshRowsQueue[i].start; + } + if (this._refreshRowsQueue[i].end > end) { + end = this._refreshRowsQueue[i].end; + } + } + } + this._refreshRowsQueue = []; + this._refreshAnimationFrame = null; + + // Render + start = Math.max(start, 0); + end = Math.min(end, this._terminal.rows - 1); + this._renderLayers.forEach(l => l.onGridChanged(this._terminal, start, end)); + this._terminal.emit('refresh', {start, end}); + } + + /** + * Recalculates the character and canvas dimensions. + */ + private _updateDimensions(): void { + // Perform a new measure if the CharMeasure dimensions are not yet available + if (!this._terminal.charMeasure.width || !this._terminal.charMeasure.height) { + return; + } + + // Calculate the scaled character width. Width is floored as it must be + // drawn to an integer grid in order for the CharAtlas "stamps" to not be + // blurry. When text is drawn to the grid not using the CharAtlas, it is + // clipped to ensure there is no overlap with the next cell. + this.dimensions.scaledCharWidth = Math.floor(this._terminal.charMeasure.width * window.devicePixelRatio); + + // Calculate the scaled character height. Height is ceiled in case + // devicePixelRatio is a floating point number in order to ensure there is + // enough space to draw the character to the cell. + this.dimensions.scaledCharHeight = Math.ceil(this._terminal.charMeasure.height * window.devicePixelRatio); + + // Calculate the scaled cell height, if lineHeight is not 1 then the value + // will be floored because since lineHeight can never be lower then 1, there + // is a guarentee that the scaled line height will always be larger than + // scaled char height. + this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._terminal.options.lineHeight); + + // Calculate the y coordinate within a cell that text should draw from in + // order to draw in the center of a cell. + this.dimensions.scaledCharTop = this._terminal.options.lineHeight === 1 ? 0 : Math.round((this.dimensions.scaledCellHeight - this.dimensions.scaledCharHeight) / 2); + + // Calculate the scaled cell width, taking the letterSpacing into account. + this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._terminal.options.letterSpacing); + + // Calculate the x coordinate with a cell that text should draw from in + // order to draw in the center of a cell. + this.dimensions.scaledCharLeft = Math.floor(this._terminal.options.letterSpacing / 2); + + // Recalculate the canvas dimensions; scaled* define the actual number of + // pixel in the canvas + this.dimensions.scaledCanvasHeight = this._terminal.rows * this.dimensions.scaledCellHeight; + this.dimensions.scaledCanvasWidth = this._terminal.cols * this.dimensions.scaledCellWidth; + + // The the size of the canvas on the page. It's very important that this + // rounds to nearest integer and not ceils as browsers often set + // window.devicePixelRatio as something like 1.100000023841858, when it's + // actually 1.1. Ceiling causes blurriness as the backing canvas image is 1 + // pixel too large for the canvas element size. + this.dimensions.canvasHeight = Math.round(this.dimensions.scaledCanvasHeight / window.devicePixelRatio); + this.dimensions.canvasWidth = Math.round(this.dimensions.scaledCanvasWidth / window.devicePixelRatio); + + // Get the _actual_ dimensions of an individual cell. This needs to be + // derived from the canvasWidth/Height calculated above which takes into + // account window.devicePixelRatio. CharMeasure.width/height by itself is + // insufficient when the page is not at 100% zoom level as CharMeasure is + // measured in CSS pixels, but the actual char size on the canvas can + // differ. + this.dimensions.actualCellHeight = this.dimensions.canvasHeight / this._terminal.rows; + this.dimensions.actualCellWidth = this.dimensions.canvasWidth / this._terminal.cols; + + } + +} diff --git a/xterm.js/src/renderer/SelectionRenderLayer.ts b/xterm.js/src/renderer/SelectionRenderLayer.ts new file mode 100644 index 0000000..9740bb9 --- /dev/null +++ b/xterm.js/src/renderer/SelectionRenderLayer.ts @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { IColorSet, IRenderDimensions } from './Interfaces'; +import { IBuffer, ICharMeasure, ITerminal } from '../Interfaces'; +import { CHAR_DATA_ATTR_INDEX } from '../Buffer'; +import { GridCache } from './GridCache'; +import { FLAGS } from './Types'; +import { BaseRenderLayer } from './BaseRenderLayer'; + +export class SelectionRenderLayer extends BaseRenderLayer { + private _state: {start: [number, number], end: [number, number]}; + + constructor(container: HTMLElement, zIndex: number, colors: IColorSet) { + super(container, 'selection', zIndex, true, colors); + this._state = { + start: null, + end: null + }; + } + + public resize(terminal: ITerminal, dim: IRenderDimensions, charSizeChanged: boolean): void { + super.resize(terminal, dim, charSizeChanged); + // Resizing the canvas discards the contents of the canvas so clear state + this._state = { + start: null, + end: null + }; + } + + public reset(terminal: ITerminal): void { + if (this._state.start && this._state.end) { + this._state = { + start: null, + end: null + }; + this.clearAll(); + } + } + + public onSelectionChanged(terminal: ITerminal, start: [number, number], end: [number, number]): void { + // Selection has not changed + if (this._state.start === start || this._state.end === end) { + return; + } + + // Remove all selections + this.clearAll(); + + // Selection does not exist + if (!start || !end) { + return; + } + + // Translate from buffer position to viewport position + const viewportStartRow = start[1] - terminal.buffer.ydisp; + const viewportEndRow = end[1] - terminal.buffer.ydisp; + const viewportCappedStartRow = Math.max(viewportStartRow, 0); + const viewportCappedEndRow = Math.min(viewportEndRow, terminal.rows - 1); + + // No need to draw the selection + if (viewportCappedStartRow >= terminal.rows || viewportCappedEndRow < 0) { + return; + } + + // Draw first row + const startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0; + const startRowEndCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : terminal.cols; + this._ctx.fillStyle = this._colors.selection; + this.fillCells(startCol, viewportCappedStartRow, startRowEndCol - startCol, 1); + + // Draw middle rows + const middleRowsCount = Math.max(viewportCappedEndRow - viewportCappedStartRow - 1, 0); + this.fillCells(0, viewportCappedStartRow + 1, terminal.cols, middleRowsCount); + + // Draw final row + if (viewportCappedStartRow !== viewportCappedEndRow) { + // Only draw viewportEndRow if it's not the same as viewportStartRow + const endCol = viewportEndRow === viewportCappedEndRow ? end[0] : terminal.cols; + this.fillCells(0, viewportCappedEndRow, endCol, 1); + } + + // Save state for next render + this._state.start = [start[0], start[1]]; + this._state.end = [end[0], end[1]]; + } +} diff --git a/xterm.js/src/renderer/TextRenderLayer.ts b/xterm.js/src/renderer/TextRenderLayer.ts new file mode 100644 index 0000000..145b205 --- /dev/null +++ b/xterm.js/src/renderer/TextRenderLayer.ts @@ -0,0 +1,249 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { IColorSet, IRenderDimensions } from './Interfaces'; +import { IBuffer, ICharMeasure, ITerminal } from '../Interfaces'; +import { CHAR_DATA_ATTR_INDEX, CHAR_DATA_CODE_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from '../Buffer'; +import { FLAGS } from './Types'; +import { GridCache } from './GridCache'; +import { CharData } from '../Types'; +import { BaseRenderLayer, INVERTED_DEFAULT_COLOR } from './BaseRenderLayer'; + +/** + * This CharData looks like a null character, which will forc a clear and render + * when the character changes (a regular space ' ' character may not as it's + * drawn state is a cleared cell). + */ +const OVERLAP_OWNED_CHAR_DATA: CharData = [null, '', 0, -1]; + +export class TextRenderLayer extends BaseRenderLayer { + private _state: GridCache; + private _characterWidth: number; + private _characterFont: string; + private _characterOverlapCache: { [key: string]: boolean } = {}; + + constructor(container: HTMLElement, zIndex: number, colors: IColorSet, alpha: + boolean) { + super(container, 'text', zIndex, alpha, colors); + this._state = new GridCache(); + } + + public resize(terminal: ITerminal, dim: IRenderDimensions, charSizeChanged: boolean): void { + super.resize(terminal, dim, charSizeChanged); + + // Clear the character width cache if the font or width has changed + const terminalFont = `${terminal.options.fontSize * window.devicePixelRatio}px ${terminal.options.fontFamily}`; + if (this._characterWidth !== dim.scaledCharWidth || this._characterFont !== terminalFont) { + this._characterWidth = dim.scaledCharWidth; + this._characterFont = terminalFont; + this._characterOverlapCache = {}; + } + // Resizing the canvas discards the contents of the canvas so clear state + this._state.clear(); + this._state.resize(terminal.cols, terminal.rows); + } + + public reset(terminal: ITerminal): void { + this._state.clear(); + this.clearAll(); + } + + public onGridChanged(terminal: ITerminal, startRow: number, endRow: number): void { + // Resize has not been called yet + if (this._state.cache.length === 0) { + return; + } + + for (let y = startRow; y <= endRow; y++) { + const row = y + terminal.buffer.ydisp; + const line = terminal.buffer.lines.get(row); + + this.clearCells(0, y, terminal.cols, 1); + // for (let x = 0; x < terminal.cols; x++) { + // this._state.cache[x][y] = null; + // } + + for (let x = 0; x < terminal.cols; x++) { + const charData = line[x]; + const code: number = charData[CHAR_DATA_CODE_INDEX]; + const char: string = charData[CHAR_DATA_CHAR_INDEX]; + const attr: number = charData[CHAR_DATA_ATTR_INDEX]; + let width: number = charData[CHAR_DATA_WIDTH_INDEX]; + + // The character to the left is a wide character, drawing is owned by + // the char at x-1 + if (width === 0) { + // this._state.cache[x][y] = null; + continue; + } + + // If the character is a space and the character to the left is an + // overlapping character, skip the character and allow the overlapping + // char to take full control over this character's cell. + if (code === 32 /*' '*/) { + if (x > 0) { + const previousChar: CharData = line[x - 1]; + if (this._isOverlapping(previousChar)) { + continue; + } + } + } + + // Skip rendering if the character is identical + // const state = this._state.cache[x][y]; + // if (state && state[CHAR_DATA_CHAR_INDEX] === char && state[CHAR_DATA_ATTR_INDEX] === attr) { + // // Skip render, contents are identical + // this._state.cache[x][y] = charData; + // continue; + // } + + // Clear the old character was not a space with the default background + // const wasInverted = !!(state && state[CHAR_DATA_ATTR_INDEX] && state[CHAR_DATA_ATTR_INDEX] >> 18 & FLAGS.INVERSE); + // if (state && !(state[CHAR_DATA_CODE_INDEX] === 32 /*' '*/ && (state[CHAR_DATA_ATTR_INDEX] & 0x1ff) >= 256 && !wasInverted)) { + // this._clearChar(x, y); + // } + // this._state.cache[x][y] = charData; + + const flags = attr >> 18; + let bg = attr & 0x1ff; + + // Skip rendering if the character is invisible + const isDefaultBackground = bg >= 256; + const isInvisible = flags & FLAGS.INVISIBLE; + const isInverted = flags & FLAGS.INVERSE; + if (!code || (code === 32 /*' '*/ && isDefaultBackground && !isInverted) || isInvisible) { + continue; + } + + // If the character is an overlapping char and the character to the right is a + // space, take ownership of the cell to the right. + if (width !== 0 && this._isOverlapping(charData)) { + // If the character is overlapping, we want to force a re-render on every + // frame. This is specifically to work around the case where two + // overlaping chars `a` and `b` are adjacent, the cursor is moved to b and a + // space is added. Without this, the first half of `b` would never + // get removed, and `a` would not re-render because it thinks it's + // already in the correct state. + // this._state.cache[x][y] = OVERLAP_OWNED_CHAR_DATA; + if (x < line.length - 1 && line[x + 1][CHAR_DATA_CODE_INDEX] === 32 /*' '*/) { + width = 2; + // this._clearChar(x + 1, y); + // The overlapping char's char data will force a clear and render when the + // overlapping char is no longer to the left of the character and also when + // the space changes to another character. + // this._state.cache[x + 1][y] = OVERLAP_OWNED_CHAR_DATA; + } + } + + let fg = (attr >> 9) & 0x1ff; + + // If inverse flag is on, the foreground should become the background. + if (isInverted) { + const temp = bg; + bg = fg; + fg = temp; + if (fg === 256) { + fg = INVERTED_DEFAULT_COLOR; + } + if (bg === 257) { + bg = INVERTED_DEFAULT_COLOR; + } + } + + // Clear the cell next to this character if it's wide + if (width === 2) { + // this.clearCells(x + 1, y, 1, 1); + } + + // Draw background + if (bg < 256) { + this._ctx.save(); + this._ctx.fillStyle = (bg === INVERTED_DEFAULT_COLOR ? this._colors.foreground : this._colors.ansi[bg]); + this.fillCells(x, y, width, 1); + this._ctx.restore(); + } + + this._ctx.save(); + if (flags & FLAGS.BOLD) { + this._ctx.font = `bold ${this._ctx.font}`; + // Convert the FG color to the bold variant + if (fg < 8) { + fg += 8; + } + } + + if (flags & FLAGS.UNDERLINE) { + if (fg === INVERTED_DEFAULT_COLOR) { + this._ctx.fillStyle = this._colors.background; + } else if (fg < 256) { + // 256 color support + this._ctx.fillStyle = this._colors.ansi[fg]; + } else { + this._ctx.fillStyle = this._colors.foreground; + } + this.fillBottomLineAtCells(x, y); + } + + this.drawChar(terminal, char, code, width, x, y, fg, bg, !!(flags & FLAGS.BOLD), !!(flags & FLAGS.DIM)); + + this._ctx.restore(); + } + } + } + + /** + * Whether a character is overlapping to the next cell. + */ + private _isOverlapping(charData: CharData): boolean { + // Only single cell characters can be overlapping, rendering issues can + // occur without this check + if (charData[CHAR_DATA_WIDTH_INDEX] !== 1) { + return false; + } + + // We assume that any ascii character will not overlap + const code = charData[CHAR_DATA_CODE_INDEX]; + if (code < 256) { + return false; + } + + // Deliver from cache if available + const char = charData[CHAR_DATA_CHAR_INDEX]; + if (this._characterOverlapCache.hasOwnProperty(char)) { + return this._characterOverlapCache[char]; + } + + // Setup the font + this._ctx.save(); + this._ctx.font = this._characterFont; + + // Measure the width of the character, but Math.floor it + // because that is what the renderer does when it calculates + // the character dimensions we are comparing against + const overlaps = Math.floor(this._ctx.measureText(char).width) > this._characterWidth; + + // Restore the original context + this._ctx.restore(); + + // Cache and return + this._characterOverlapCache[char] = overlaps; + return overlaps; + } + + /** + * Clear the charcater at the cell specified. + * @param x The column of the char. + * @param y The row of the char. + */ + private _clearChar(x: number, y: number): void { + let colsToClear = 1; + // Clear the adjacent character if it was wide + const state = this._state.cache[x][y]; + if (state && state[CHAR_DATA_WIDTH_INDEX] === 2) { + colsToClear = 2; + } + this.clearCells(x, y, colsToClear, 1); + } +} diff --git a/xterm.js/src/renderer/Types.ts b/xterm.js/src/renderer/Types.ts new file mode 100644 index 0000000..31705a3 --- /dev/null +++ b/xterm.js/src/renderer/Types.ts @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + + /** + * Flags used to render terminal text properly. + */ +export enum FLAGS { + BOLD = 1, + UNDERLINE = 2, + BLINK = 4, + INVERSE = 8, + INVISIBLE = 16, + DIM = 32 +}; diff --git a/xterm.js/src/utils/Browser.ts b/xterm.js/src/utils/Browser.ts new file mode 100644 index 0000000..48c0c37 --- /dev/null +++ b/xterm.js/src/utils/Browser.ts @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { contains } from './Generic'; + +const isNode = (typeof navigator === 'undefined') ? true : false; +const userAgent = (isNode) ? 'node' : navigator.userAgent; +const platform = (isNode) ? 'node' : navigator.platform; + +export const isFirefox = !!~userAgent.indexOf('Firefox'); +export const isMSIE = !!~userAgent.indexOf('MSIE') || !!~userAgent.indexOf('Trident'); + +// Find the users platform. We use this to interpret the meta key +// and ISO third level shifts. +// http://stackoverflow.com/q/19877924/577598 +export const isMac = contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform); +export const isIpad = platform === 'iPad'; +export const isIphone = platform === 'iPhone'; +export const isMSWindows = contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform); +export const isLinux = platform.indexOf('Linux') >= 0; diff --git a/xterm.js/src/utils/CharMeasure.test.ts b/xterm.js/src/utils/CharMeasure.test.ts new file mode 100644 index 0000000..f50ce96 --- /dev/null +++ b/xterm.js/src/utils/CharMeasure.test.ts @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import jsdom = require('jsdom'); +import { assert } from 'chai'; +import { ICharMeasure, ITerminal } from '../Interfaces'; +import { CharMeasure } from './CharMeasure'; + +describe('CharMeasure', () => { + let dom: jsdom.JSDOM; + let window: Window; + let document: Document; + let container: HTMLElement; + let charMeasure: ICharMeasure; + + beforeEach(() => { + dom = new jsdom.JSDOM(''); + window = dom.window; + document = window.document; + container = document.createElement('div'); + document.body.appendChild(container); + charMeasure = new CharMeasure(document, container); + }); + + describe('measure', () => { + it('should have _measureElement', () => { + assert.isDefined((charMeasure)._measureElement, 'new CharMeasure() should have created _measureElement'); + }); + + it('should be performed sync', () => { + // Mock getBoundingClientRect since jsdom doesn't have a layout engine + (charMeasure)._measureElement.getBoundingClientRect = () => { + return { width: 1, height: 1 }; + }; + charMeasure.measure({}); + assert.equal(charMeasure.height, 1); + assert.equal(charMeasure.width, 1); + }); + + it('should NOT do a measure when the parent is hidden', done => { + charMeasure.measure({}); + setTimeout(() => { + const firstWidth = charMeasure.width; + container.style.display = 'none'; + container.style.fontSize = '2em'; + charMeasure.measure({}); + assert.equal(charMeasure.width, firstWidth); + done(); + }, 0); + }); + }); +}); diff --git a/xterm.js/src/utils/CharMeasure.ts b/xterm.js/src/utils/CharMeasure.ts new file mode 100644 index 0000000..62291ab --- /dev/null +++ b/xterm.js/src/utils/CharMeasure.ts @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { EventEmitter } from '../EventEmitter'; +import { ICharMeasure, ITerminal, ITerminalOptions } from '../Interfaces'; + +/** + * Utility class that measures the size of a character. Measurements are done in + * the DOM rather than with a canvas context because support for extracting the + * height of characters is patchy across browsers. + */ +export class CharMeasure extends EventEmitter implements ICharMeasure { + private _document: Document; + private _parentElement: HTMLElement; + private _measureElement: HTMLElement; + private _width: number; + private _height: number; + + constructor(document: Document, parentElement: HTMLElement) { + super(); + this._document = document; + this._parentElement = parentElement; + this._measureElement = this._document.createElement('span'); + this._measureElement.style.position = 'absolute'; + this._measureElement.style.top = '0'; + this._measureElement.style.left = '-9999em'; + this._measureElement.style.lineHeight = 'normal'; + this._measureElement.textContent = 'W'; + this._measureElement.setAttribute('aria-hidden', 'true'); + this._parentElement.appendChild(this._measureElement); + } + + public get width(): number { + return this._width; + } + + public get height(): number { + return this._height; + } + + public measure(options: ITerminalOptions): void { + this._measureElement.style.fontFamily = options.fontFamily; + this._measureElement.style.fontSize = `${options.fontSize}px`; + const geometry = this._measureElement.getBoundingClientRect(); + // The element is likely currently display:none, we should retain the + // previous value. + if (geometry.width === 0 || geometry.height === 0) { + return; + } + if (this._width !== geometry.width || this._height !== geometry.height) { + this._width = geometry.width; + this._height = Math.ceil(geometry.height); + this.emit('charsizechanged'); + } + } + +} diff --git a/xterm.js/src/utils/CircularList.test.ts b/xterm.js/src/utils/CircularList.test.ts new file mode 100644 index 0000000..6bb3511 --- /dev/null +++ b/xterm.js/src/utils/CircularList.test.ts @@ -0,0 +1,264 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { assert } from 'chai'; +import { CircularList } from './CircularList'; + +class TestCircularList extends CircularList { + public get array(): T[] { return this._array; } +} + +describe('CircularList', () => { + describe('push', () => { + it('should push values onto the array', () => { + const list = new CircularList(5); + list.push('1'); + list.push('2'); + list.push('3'); + list.push('4'); + list.push('5'); + assert.equal(list.get(0), '1'); + assert.equal(list.get(1), '2'); + assert.equal(list.get(2), '3'); + assert.equal(list.get(3), '4'); + assert.equal(list.get(4), '5'); + }); + + it('should push old values from the start out of the array when max length is reached', () => { + const list = new CircularList(2); + list.push('1'); + list.push('2'); + assert.equal(list.get(0), '1'); + assert.equal(list.get(1), '2'); + list.push('3'); + assert.equal(list.get(0), '2'); + assert.equal(list.get(1), '3'); + list.push('4'); + assert.equal(list.get(0), '3'); + assert.equal(list.get(1), '4'); + }); + }); + + describe('maxLength', () => { + it('should increase the size of the list', () => { + const list = new CircularList(2); + list.push('1'); + list.push('2'); + assert.equal(list.get(0), '1'); + assert.equal(list.get(1), '2'); + list.maxLength = 4; + list.push('3'); + list.push('4'); + assert.equal(list.get(0), '1'); + assert.equal(list.get(1), '2'); + assert.equal(list.get(2), '3'); + assert.equal(list.get(3), '4'); + list.push('wrapped'); + assert.equal(list.get(0), '2'); + assert.equal(list.get(1), '3'); + assert.equal(list.get(2), '4'); + assert.equal(list.get(3), 'wrapped'); + }); + + it('should return the maximum length of the list', () => { + const list = new CircularList(2); + assert.equal(list.maxLength, 2); + list.push('1'); + list.push('2'); + assert.equal(list.maxLength, 2); + list.push('3'); + assert.equal(list.maxLength, 2); + list.maxLength = 4; + assert.equal(list.maxLength, 4); + }); + }); + + describe('length', () => { + it('should return the current length of the list, capped at the maximum length', () => { + const list = new CircularList(2); + assert.equal(list.length, 0); + list.push('1'); + assert.equal(list.length, 1); + list.push('2'); + assert.equal(list.length, 2); + list.push('3'); + assert.equal(list.length, 2); + }); + }); + + describe('splice', () => { + it('should delete items', () => { + const list = new CircularList(2); + list.push('1'); + list.push('2'); + list.splice(0, 1); + assert.equal(list.length, 1); + assert.equal(list.get(0), '2'); + list.push('3'); + list.splice(1, 1); + assert.equal(list.length, 1); + assert.equal(list.get(0), '2'); + }); + + it('should insert items', () => { + const list = new CircularList(2); + list.push('1'); + list.splice(0, 0, '2'); + assert.equal(list.length, 2); + assert.equal(list.get(0), '2'); + assert.equal(list.get(1), '1'); + list.splice(1, 0, '3'); + assert.equal(list.length, 2); + assert.equal(list.get(0), '3'); + assert.equal(list.get(1), '1'); + }); + + it('should delete items then insert items', () => { + const list = new CircularList(3); + list.push('1'); + list.push('2'); + list.splice(0, 1, '3', '4'); + assert.equal(list.length, 3); + assert.equal(list.get(0), '3'); + assert.equal(list.get(1), '4'); + assert.equal(list.get(2), '2'); + }); + + it('should wrap the array correctly when more items are inserted than deleted', () => { + const list = new CircularList(3); + list.push('1'); + list.push('2'); + list.splice(1, 0, '3', '4'); + assert.equal(list.length, 3); + assert.equal(list.get(0), '3'); + assert.equal(list.get(1), '4'); + assert.equal(list.get(2), '2'); + }); + }); + + describe('trimStart', () => { + it('should remove items from the beginning of the list', () => { + const list = new CircularList(5); + list.push('1'); + list.push('2'); + list.push('3'); + list.push('4'); + list.push('5'); + list.trimStart(1); + assert.equal(list.length, 4); + assert.deepEqual(list.get(0), '2'); + assert.deepEqual(list.get(1), '3'); + assert.deepEqual(list.get(2), '4'); + assert.deepEqual(list.get(3), '5'); + list.trimStart(2); + assert.equal(list.length, 2); + assert.deepEqual(list.get(0), '4'); + assert.deepEqual(list.get(1), '5'); + }); + + it('should remove all items if the requested trim amount is larger than the list\'s length', () => { + const list = new CircularList(5); + list.push('1'); + list.trimStart(2); + assert.equal(list.length, 0); + }); + }); + + describe('shiftElements', () => { + it('should not mutate the list when count is 0', () => { + const list = new CircularList(5); + list.push(1); + list.push(2); + list.shiftElements(0, 0, 1); + assert.equal(list.length, 2); + assert.equal(list.get(0), 1); + assert.equal(list.get(1), 2); + }); + + it('should throw for invalid args', () => { + const list = new CircularList(5); + list.push(1); + assert.throws(() => list.shiftElements(-1, 1, 1), 'start argument out of range'); + assert.throws(() => list.shiftElements(1, 1, 1), 'start argument out of range'); + assert.throws(() => list.shiftElements(0, 1, -1), 'Cannot shift elements in list beyond index 0'); + }); + + it('should shift an element forward', () => { + const list = new CircularList(5); + list.push(1); + list.push(2); + list.shiftElements(0, 1, 1); + assert.equal(list.length, 2); + assert.equal(list.get(0), 1); + assert.equal(list.get(1), 1); + }); + + it('should shift elements forward', () => { + const list = new CircularList(5); + list.push(1); + list.push(2); + list.push(3); + list.push(4); + list.shiftElements(0, 2, 2); + assert.equal(list.length, 4); + assert.equal(list.get(0), 1); + assert.equal(list.get(1), 2); + assert.equal(list.get(2), 1); + assert.equal(list.get(3), 2); + }); + + it('should shift elements forward, expanding the list if needed', () => { + const list = new CircularList(5); + list.push(1); + list.push(2); + list.shiftElements(0, 2, 2); + assert.equal(list.length, 4); + assert.equal(list.get(0), 1); + assert.equal(list.get(1), 2); + assert.equal(list.get(2), 1); + assert.equal(list.get(3), 2); + }); + + it('should shift elements forward, wrapping the list if needed', () => { + const list = new CircularList(5); + list.push(1); + list.push(2); + list.push(3); + list.push(4); + list.push(5); + list.shiftElements(2, 2, 3); + assert.equal(list.length, 5); + assert.equal(list.get(0), 3); + assert.equal(list.get(1), 4); + assert.equal(list.get(2), 5); + assert.equal(list.get(3), 3); + assert.equal(list.get(4), 4); + }); + + it('should shift an element backwards', () => { + const list = new CircularList(5); + list.push(1); + list.push(2); + list.shiftElements(1, 1, -1); + assert.equal(list.length, 2); + assert.equal(list.get(0), 2); + assert.equal(list.get(1), 2); + }); + + it('should shift elements backwards', () => { + const list = new CircularList(5); + list.push(1); + list.push(2); + list.push(3); + list.push(4); + list.shiftElements(2, 2, -2); + assert.equal(list.length, 4); + assert.equal(list.get(0), 3); + assert.equal(list.get(1), 4); + assert.equal(list.get(2), 3); + assert.equal(list.get(3), 4); + }); + }); +}); diff --git a/xterm.js/src/utils/CircularList.ts b/xterm.js/src/utils/CircularList.ts new file mode 100644 index 0000000..97a32b7 --- /dev/null +++ b/xterm.js/src/utils/CircularList.ts @@ -0,0 +1,213 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { EventEmitter } from '../EventEmitter'; +import { ICircularList } from '../Interfaces'; + +/** + * Represents a circular list; a list with a maximum size that wraps around when push is called, + * overriding values at the start of the list. + */ +export class CircularList extends EventEmitter implements ICircularList { + protected _array: T[]; + private _startIndex: number; + private _length: number; + + constructor( + private _maxLength: number + ) { + super(); + this._array = new Array(this._maxLength); + this._startIndex = 0; + this._length = 0; + } + + public get maxLength(): number { + return this._maxLength; + } + + public set maxLength(newMaxLength: number) { + // There was no change in maxLength, return early. + if (this._maxLength === newMaxLength) { + return; + } + + // Reconstruct array, starting at index 0. Only transfer values from the + // indexes 0 to length. + let newArray = new Array(newMaxLength); + for (let i = 0; i < Math.min(newMaxLength, this.length); i++) { + newArray[i] = this._array[this._getCyclicIndex(i)]; + } + this._array = newArray; + this._maxLength = newMaxLength; + this._startIndex = 0; + } + + public get length(): number { + return this._length; + } + + public set length(newLength: number) { + if (newLength > this._length) { + for (let i = this._length; i < newLength; i++) { + this._array[i] = undefined; + } + } + this._length = newLength; + } + + public get forEach(): (callbackfn: (value: T, index: number) => void) => void { + return (callbackfn: (value: T, index: number) => void) => { + let i = 0; + let length = this.length; + for (let i = 0; i < length; i++) { + callbackfn(this.get(i), i); + } + }; + } + + /** + * Gets the value at an index. + * + * Note that for performance reasons there is no bounds checking here, the index reference is + * circular so this should always return a value and never throw. + * @param index The index of the value to get. + * @return The value corresponding to the index. + */ + public get(index: number): T { + return this._array[this._getCyclicIndex(index)]; + } + + /** + * Sets the value at an index. + * + * Note that for performance reasons there is no bounds checking here, the index reference is + * circular so this should always return a value and never throw. + * @param index The index to set. + * @param value The value to set. + */ + public set(index: number, value: T): void { + this._array[this._getCyclicIndex(index)] = value; + } + + /** + * Pushes a new value onto the list, wrapping around to the start of the array, overriding index 0 + * if the maximum length is reached. + * @param value The value to push onto the list. + */ + public push(value: T): void { + this._array[this._getCyclicIndex(this._length)] = value; + if (this._length === this._maxLength) { + this._startIndex++; + if (this._startIndex === this._maxLength) { + this._startIndex = 0; + } + this.emit('trim', 1); + } else { + this._length++; + } + } + + /** + * Removes and returns the last value on the list. + * @return The popped value. + */ + public pop(): T { + return this._array[this._getCyclicIndex(this._length-- - 1)]; + } + + /** + * Deletes and/or inserts items at a particular index (in that order). Unlike + * Array.prototype.splice, this operation does not return the deleted items as a new array in + * order to save creating a new array. Note that this operation may shift all values in the list + * in the worst case. + * @param start The index to delete and/or insert. + * @param deleteCount The number of elements to delete. + * @param items The items to insert. + */ + public splice(start: number, deleteCount: number, ...items: T[]): void { + // Delete items + if (deleteCount) { + for (let i = start; i < this._length - deleteCount; i++) { + this._array[this._getCyclicIndex(i)] = this._array[this._getCyclicIndex(i + deleteCount)]; + } + this._length -= deleteCount; + } + + if (items && items.length) { + // Add items + for (let i = this._length - 1; i >= start; i--) { + this._array[this._getCyclicIndex(i + items.length)] = this._array[this._getCyclicIndex(i)]; + } + for (let i = 0; i < items.length; i++) { + this._array[this._getCyclicIndex(start + i)] = items[i]; + } + + // Adjust length as needed + if (this._length + items.length > this.maxLength) { + const countToTrim = (this._length + items.length) - this.maxLength; + this._startIndex += countToTrim; + this._length = this.maxLength; + this.emit('trim', countToTrim); + } else { + this._length += items.length; + } + } + } + + /** + * Trims a number of items from the start of the list. + * @param count The number of items to remove. + */ + public trimStart(count: number): void { + if (count > this._length) { + count = this._length; + } + this._startIndex += count; + this._length -= count; + this.emit('trim', count); + } + + public shiftElements(start: number, count: number, offset: number): void { + if (count <= 0) { + return; + } + if (start < 0 || start >= this._length) { + throw new Error('start argument out of range'); + } + if (start + offset < 0) { + throw new Error('Cannot shift elements in list beyond index 0'); + } + + if (offset > 0) { + for (let i = count - 1; i >= 0; i--) { + this.set(start + i + offset, this.get(start + i)); + } + const expandListBy = (start + count + offset) - this._length; + if (expandListBy > 0) { + this._length += expandListBy; + while (this._length > this.maxLength) { + this._length--; + this._startIndex++; + this.emit('trim', 1); + } + } + } else { + for (let i = 0; i < count; i++) { + this.set(start + i + offset, this.get(start + i)); + } + } + } + + /** + * Gets the cyclic index for the specified regular index. The cyclic index can then be used on the + * backing array to get the element associated with the regular index. + * @param index The regular index. + * @returns The cyclic index. + */ + private _getCyclicIndex(index: number): number { + return (this._startIndex + index) % this.maxLength; + } +} diff --git a/xterm.js/src/utils/Generic.ts b/xterm.js/src/utils/Generic.ts new file mode 100644 index 0000000..8237361 --- /dev/null +++ b/xterm.js/src/utils/Generic.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) 2016 The xterm.js authors. All rights reserved. + * @license MIT + */ + +/** + * Return if the given array contains the given element + * @param {Array} array The array to search for the given element. + * @param {Object} el The element to look for into the array + */ +export function contains(arr: any[], el: any): boolean { + return arr.indexOf(el) >= 0; +}; diff --git a/xterm.js/src/utils/MouseHelper.test.ts b/xterm.js/src/utils/MouseHelper.test.ts new file mode 100644 index 0000000..ac3137f --- /dev/null +++ b/xterm.js/src/utils/MouseHelper.test.ts @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import jsdom = require('jsdom'); +import { assert } from 'chai'; +import { MouseHelper } from './MouseHelper'; +import { MockCharMeasure, MockRenderer } from './TestUtils.test'; + +const CHAR_WIDTH = 10; +const CHAR_HEIGHT = 20; + +describe('MouseHelper.getCoords', () => { + let dom: jsdom.JSDOM; + let window: Window; + let document: Document; + let mouseHelper: MouseHelper; + + let charMeasure: MockCharMeasure; + + beforeEach(() => { + dom = new jsdom.JSDOM(''); + window = dom.window; + document = window.document; + charMeasure = new MockCharMeasure(); + charMeasure.width = CHAR_WIDTH; + charMeasure.height = CHAR_HEIGHT; + const renderer = new MockRenderer(); + renderer.dimensions = { + actualCellWidth: CHAR_WIDTH, + actualCellHeight: CHAR_HEIGHT + }; + mouseHelper = new MouseHelper(renderer); + }); + + describe('when charMeasure is not initialized', () => { + it('should return null', () => { + charMeasure = new MockCharMeasure(); + assert.equal(mouseHelper.getCoords({ pageX: 0, pageY: 0 }, document.createElement('div'), charMeasure, 1, 10, 10), null); + }); + }); + + describe('when pageX/pageY are not supported', () => { + it('should return null', () => { + assert.equal(mouseHelper.getCoords({ pageX: undefined, pageY: undefined }, document.createElement('div'), charMeasure, 1, 10, 10), null); + }); + }); + + it('should return the cell that was clicked', () => { + let coords: [number, number]; + coords = mouseHelper.getCoords({ pageX: CHAR_WIDTH / 2, pageY: CHAR_HEIGHT / 2 }, document.createElement('div'), charMeasure, 1, 10, 10); + assert.deepEqual(coords, [1, 1]); + coords = mouseHelper.getCoords({ pageX: CHAR_WIDTH, pageY: CHAR_HEIGHT }, document.createElement('div'), charMeasure, 1, 10, 10); + assert.deepEqual(coords, [1, 1]); + coords = mouseHelper.getCoords({ pageX: CHAR_WIDTH, pageY: CHAR_HEIGHT + 1 }, document.createElement('div'), charMeasure, 1, 10, 10); + assert.deepEqual(coords, [1, 2]); + coords = mouseHelper.getCoords({ pageX: CHAR_WIDTH + 1, pageY: CHAR_HEIGHT }, document.createElement('div'), charMeasure, 1, 10, 10); + assert.deepEqual(coords, [2, 1]); + }); + + it('should ensure the coordinates are returned within the terminal bounds', () => { + let coords: [number, number]; + coords = mouseHelper.getCoords({ pageX: -1, pageY: -1 }, document.createElement('div'), charMeasure, 1, 10, 10); + assert.deepEqual(coords, [1, 1]); + // Event are double the cols/rows + coords = mouseHelper.getCoords({ pageX: CHAR_WIDTH * 20, pageY: CHAR_HEIGHT * 20 }, document.createElement('div'), charMeasure, 1, 10, 10); + assert.deepEqual(coords, [10, 10], 'coordinates should never come back as larger than the terminal'); + }); +}); diff --git a/xterm.js/src/utils/MouseHelper.ts b/xterm.js/src/utils/MouseHelper.ts new file mode 100644 index 0000000..d7d8f69 --- /dev/null +++ b/xterm.js/src/utils/MouseHelper.ts @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ICharMeasure } from '../Interfaces'; +import { IRenderer } from '../renderer/Interfaces'; + +export class MouseHelper { + constructor(private _renderer: IRenderer) {} + + public static getCoordsRelativeToElement(event: {pageX: number, pageY: number}, element: HTMLElement): [number, number] { + // Ignore browsers that don't support MouseEvent.pageX + if (event.pageX == null) { + return null; + } + + const originalElement = element; + let x = event.pageX; + let y = event.pageY; + + // Converts the coordinates from being relative to the document to being + // relative to the terminal. + while (element) { + x -= element.offsetLeft; + y -= element.offsetTop; + element = 'offsetParent' in element ? element.offsetParent : element.parentElement; + } + element = originalElement; + while (element && element !== element.ownerDocument.body) { + x += element.scrollLeft; + y += element.scrollTop; + element = element.parentElement; + } + return [x, y]; + } + + /** + * Gets coordinates within the terminal for a particular mouse event. The result + * is returned as an array in the form [x, y] instead of an object as it's a + * little faster and this function is used in some low level code. + * @param event The mouse event. + * @param element The terminal's container element. + * @param charMeasure The char measure object used to determine character sizes. + * @param colCount The number of columns in the terminal. + * @param rowCount The number of rows n the terminal. + * @param isSelection Whether the request is for the selection or not. This will + * apply an offset to the x value such that the left half of the cell will + * select that cell and the right half will select the next cell. + */ + public getCoords(event: {pageX: number, pageY: number}, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number, isSelection?: boolean): [number, number] { + // Coordinates cannot be measured if charMeasure has not been initialized + if (!charMeasure.width || !charMeasure.height) { + return null; + } + + const coords = MouseHelper.getCoordsRelativeToElement(event, element); + if (!coords) { + return null; + } + + coords[0] = Math.ceil((coords[0] + (isSelection ? this._renderer.dimensions.actualCellWidth / 2 : 0)) / this._renderer.dimensions.actualCellWidth); + coords[1] = Math.ceil(coords[1] / this._renderer.dimensions.actualCellHeight); + + // Ensure coordinates are within the terminal viewport. Note that selections + // need an addition point of precision to cover the end point (as characters + // cover half of one char and half of the next). + coords[0] = Math.min(Math.max(coords[0], 1), colCount + (isSelection ? 1 : 0)); + coords[1] = Math.min(Math.max(coords[1], 1), rowCount); + + return coords; + } + + /** + * Gets coordinates within the terminal for a particular mouse event, wrapping + * them to the bounds of the terminal and adding 32 to both the x and y values + * as expected by xterm. + * @param event The mouse event. + * @param element The terminal's container element. + * @param charMeasure The char measure object used to determine character sizes. + * @param colCount The number of columns in the terminal. + * @param rowCount The number of rows in the terminal. + */ + public getRawByteCoords(event: MouseEvent, element: HTMLElement, charMeasure: ICharMeasure, lineHeight: number, colCount: number, rowCount: number): { x: number, y: number } { + const coords = this.getCoords(event, element, charMeasure, lineHeight, colCount, rowCount); + let x = coords[0]; + let y = coords[1]; + + // xterm sends raw bytes and starts at 32 (SP) for each. + x += 32; + y += 32; + + return { x, y }; + } +} diff --git a/xterm.js/src/utils/ScreenDprMonitor.ts b/xterm.js/src/utils/ScreenDprMonitor.ts new file mode 100644 index 0000000..15f3ac0 --- /dev/null +++ b/xterm.js/src/utils/ScreenDprMonitor.ts @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +export type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRatio?: number) => void; + +/** + * The screen device pixel ratio monitor allows listening for when the + * window.devicePixelRatio value changes. This is done not with polling but with + * the use of window.matchMedia to watch media queries. When the event fires, + * the listener will be reattached using a different media query to ensure that + * any further changes will register. + * + * The listener should fire on both window zoom changes and switching to a + * monitor with a different DPI. + */ +export class ScreenDprMonitor { + private _currentDevicePixelRatio: number; + private _outerListener: MediaQueryListListener; + private _listener: ScreenDprListener; + private _resolutionMediaMatchList: MediaQueryList; + + public setListener(listener: ScreenDprListener): void { + if (this._listener) { + this.clearListener(); + } + this._listener = listener; + this._outerListener = () => { + this._listener(window.devicePixelRatio, this._currentDevicePixelRatio); + this._updateDpr(); + }; + this._updateDpr(); + } + + private _updateDpr(): void { + // Clear listeners for old DPR + if (this._resolutionMediaMatchList) { + this._resolutionMediaMatchList.removeListener(this._outerListener); + } + // Add listeners for new DPR + this._currentDevicePixelRatio = window.devicePixelRatio; + this._resolutionMediaMatchList = window.matchMedia(`screen and (resolution: ${window.devicePixelRatio}dppx)`); + this._resolutionMediaMatchList.addListener(this._outerListener); + } + + public clearListener(): void { + if (!this._listener) { + return; + } + this._resolutionMediaMatchList.removeListener(this._outerListener); + this._listener = null; + this._outerListener = null; + } +} diff --git a/xterm.js/src/utils/Sounds.ts b/xterm.js/src/utils/Sounds.ts new file mode 100644 index 0000000..03f36f4 --- /dev/null +++ b/xterm.js/src/utils/Sounds.ts @@ -0,0 +1,10 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +// Source: https://freesound.org/people/altemark/sounds/45759/ +// This sound is released under the Creative Commons Attribution 3.0 Unported +// (CC BY 3.0) license. It was created by 'altemark'. No modifications have been +// made, apart from the conversion to base64. +export const BellSound = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQBAADpAFgCwAMlBZoG/wdmCcoKRAypDQ8PbRDBEQQTOxRtFYcWlBePGIUZXhoiG88bcBz7HHIdzh0WHlMeZx51HmkeUx4WHs8dah0AHXwc3hs9G4saxRnyGBIYGBcQFv8U4RPAEoYRQBACD70NWwwHC6gJOwjWBloF7gOBAhABkf8b/qv8R/ve+Xf4Ife79W/0JfPZ8Z/wde9N7ijtE+wU6xvqM+lb6H7nw+YX5mrlxuQz5Mzje+Ma49fioeKD4nXiYeJy4pHitOL04j/jn+MN5IPkFOWs5U3mDefM55/ogOl36m7rdOyE7abuyu8D8Unyj/Pg9D/2qfcb+Yn6/vuK/Qj/lAAlAg=='; diff --git a/xterm.js/src/utils/TestUtils.test.ts b/xterm.js/src/utils/TestUtils.test.ts new file mode 100644 index 0000000..80e2527 --- /dev/null +++ b/xterm.js/src/utils/TestUtils.test.ts @@ -0,0 +1,278 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, IListenerType, IInputHandlingTerminal, IViewport, ICircularList, ICompositionHelper, ITheme, ILinkifier, IMouseHelper } from '../Interfaces'; +import { LineData } from '../Types'; +import { Buffer } from '../Buffer'; +import * as Browser from './Browser'; +import { IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../renderer/Interfaces'; + +export class MockTerminal implements ITerminal { + bracketedPasteMode: boolean; + mouseHelper: IMouseHelper; + renderer: IRenderer; + linkifier: ILinkifier; + isFocused: boolean; + options: ITerminalOptions = {}; + element: HTMLElement; + rowContainer: HTMLElement; + selectionContainer: HTMLElement; + selectionManager: ISelectionManager; + charMeasure: ICharMeasure; + textarea: HTMLTextAreaElement; + rows: number; + cols: number; + browser: IBrowser = Browser; + writeBuffer: string[]; + children: HTMLElement[]; + cursorHidden: boolean; + cursorState: number; + defAttr: number; + scrollback: number; + buffers: IBufferSet; + buffer: IBuffer; + handler(data: string): void { + throw new Error('Method not implemented.'); + } + on(event: string, callback: () => void): void { + throw new Error('Method not implemented.'); + } + off(type: string, listener: IListenerType): void { + throw new Error('Method not implemented.'); + } + scrollLines(disp: number, suppressScrollEvent: boolean): void { + throw new Error('Method not implemented.'); + } + cancel(ev: Event, force?: boolean): void { + throw new Error('Method not implemented.'); + } + log(text: string): void { + throw new Error('Method not implemented.'); + } + emit(event: string, data: any): void { + throw new Error('Method not implemented.'); + } + reset(): void { + throw new Error('Method not implemented.'); + } + showCursor(): void { + throw new Error('Method not implemented.'); + } + refresh(start: number, end: number): void { + throw new Error('Method not implemented.'); + } + blankLine(cur?: boolean, isWrapped?: boolean, cols?: number): LineData { + const line: LineData = []; + cols = cols || this.cols; + for (let i = 0; i < cols; i++) { + line.push([0, ' ', 1, 32]); + } + return line; + } +} + +export class MockCharMeasure implements ICharMeasure { + width: number; + height: number; + measure(options: ITerminalOptions): void { + throw new Error('Method not implemented.'); + } +} + +export class MockInputHandlingTerminal implements IInputHandlingTerminal { + element: HTMLElement; + options: ITerminalOptions = {}; + cols: number; + rows: number; + charset: { [key: string]: string; }; + gcharset: number; + glevel: number; + charsets: { [key: string]: string; }[]; + applicationKeypad: boolean; + applicationCursor: boolean; + originMode: boolean; + insertMode: boolean; + wraparoundMode: boolean; + bracketedPasteMode: boolean; + defAttr: number; + curAttr: number; + prefix: string; + savedCols: number; + x10Mouse: boolean; + vt200Mouse: boolean; + normalMouse: boolean; + mouseEvents: boolean; + sendFocus: boolean; + utfMouse: boolean; + sgrMouse: boolean; + urxvtMouse: boolean; + cursorHidden: boolean; + buffers: IBufferSet; + buffer: IBuffer = new MockBuffer(); + viewport: IViewport; + selectionManager: ISelectionManager; + focus(): void { + throw new Error('Method not implemented.'); + } + convertEol: boolean; + bell(): void { + throw new Error('Method not implemented.'); + } + + updateRange(y: number): void { + throw new Error('Method not implemented.'); + } + scroll(isWrapped?: boolean): void { + throw new Error('Method not implemented.'); + } + nextStop(x?: number): number { + throw new Error('Method not implemented.'); + } + setgLevel(g: number): void { + throw new Error('Method not implemented.'); + } + eraseAttr(): number { + throw new Error('Method not implemented.'); + } + eraseRight(x: number, y: number): void { + throw new Error('Method not implemented.'); + } + eraseLine(y: number): void { + throw new Error('Method not implemented.'); + } + eraseLeft(x: number, y: number): void { + throw new Error('Method not implemented.'); + } + blankLine(cur?: boolean, isWrapped?: boolean): [number, string, number, number][] { + throw new Error('Method not implemented.'); + } + prevStop(x?: number): number { + throw new Error('Method not implemented.'); + } + is(term: string): boolean { + throw new Error('Method not implemented.'); + } + send(data: string): void { + throw new Error('Method not implemented.'); + } + setgCharset(g: number, charset: { [key: string]: string; }): void { + throw new Error('Method not implemented.'); + } + resize(x: number, y: number): void { + throw new Error('Method not implemented.'); + } + log(text: string, data?: any): void { + throw new Error('Method not implemented.'); + } + reset(): void { + throw new Error('Method not implemented.'); + } + showCursor(): void { + throw new Error('Method not implemented.'); + } + refresh(start: number, end: number): void { + throw new Error('Method not implemented.'); + } + matchColor(r1: number, g1: number, b1: number): number { + throw new Error('Method not implemented.'); + } + error(text: string, data?: any): void { + throw new Error('Method not implemented.'); + } + setOption(key: string, value: any): void { + this.options[key] = value; + } + on(type: string, listener: IListenerType): void { + throw new Error('Method not implemented.'); + } + off(type: string, listener: IListenerType): void { + throw new Error('Method not implemented.'); + } + emit(type: string, data?: any): void { + throw new Error('Method not implemented.'); + } +} + +export class MockBuffer implements IBuffer { + isCursorInViewport: boolean; + lines: ICircularList<[number, string, number, number][]>; + ydisp: number; + ybase: number; + y: number; + x: number; + tabs: any; + scrollBottom: number; + scrollTop: number; + savedY: number; + savedX: number; + translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string { + return Buffer.prototype.translateBufferLineToString.apply(this, arguments); + } + nextStop(x?: number): number { + throw new Error('Method not implemented.'); + } + prevStop(x?: number): number { + throw new Error('Method not implemented.'); + } +} + +export class MockRenderer implements IRenderer { + colorManager: IColorManager; + on(type: string, listener: IListenerType): void { + throw new Error('Method not implemented.'); + } + off(type: string, listener: IListenerType): void { + throw new Error('Method not implemented.'); + } + emit(type: string, data?: any): void { + throw new Error('Method not implemented.'); + } + dimensions: IRenderDimensions; + setTheme(theme: ITheme): IColorSet { return {}; } + onResize(cols: number, rows: number, didCharSizeChange: boolean): void {} + onCharSizeChanged(): void {} + onBlur(): void {} + onFocus(): void {} + onSelectionChanged(start: [number, number], end: [number, number]): void {} + onCursorMove(): void {} + onOptionsChanged(): void {} + onWindowResize(devicePixelRatio: number): void {} + clear(): void {} + queueRefresh(start: number, end: number): void {} +} + +export class MockViewport implements IViewport { + onThemeChanged(colors: IColorSet): void { + throw new Error('Method not implemented.'); + } + onWheel(ev: WheelEvent): void { + throw new Error('Method not implemented.'); + } + onTouchStart(ev: TouchEvent): void { + throw new Error('Method not implemented.'); + } + onTouchMove(ev: TouchEvent): void { + throw new Error('Method not implemented.'); + } + syncScrollArea(): void { } +} + +export class MockCompositionHelper implements ICompositionHelper { + compositionstart(): void { + throw new Error('Method not implemented.'); + } + compositionupdate(ev: CompositionEvent): void { + throw new Error('Method not implemented.'); + } + compositionend(): void { + throw new Error('Method not implemented.'); + } + updateCompositionElements(dontRecurse?: boolean): void { + throw new Error('Method not implemented.'); + } + keydown(ev: KeyboardEvent): boolean { + return true; + } +} diff --git a/xterm.js/src/xterm.css b/xterm.js/src/xterm.css new file mode 100644 index 0000000..b3ee50f --- /dev/null +++ b/xterm.js/src/xterm.css @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2014 The xterm.js authors. All rights reserved. + * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) + * https://github.com/chjj/term.js + * @license MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Originally forked from (with the author's permission): + * Fabrice Bellard's javascript vt100 for jslinux: + * http://bellard.org/jslinux/ + * Copyright (c) 2011 Fabrice Bellard + * The original design remains. The terminal itself + * has been extended to include xterm CSI codes, among + * other features. + */ + +/** + * Default styles for xterm.js + */ + +.xterm { + font-family: courier-new, courier, monospace; + font-feature-settings: "liga" 0; + position: relative; + user-select: none; + -ms-user-select: none; + -webkit-user-select: none; +} + +.xterm.focus, +.xterm:focus { + outline: none; +} + +.xterm .xterm-helpers { + position: absolute; + top: 0; + /** + * The z-index of the helpers must be higher than the canvases in order for + * IMEs to appear on top. + */ + z-index: 10; +} + +.xterm .xterm-helper-textarea { + /* + * HACK: to fix IE's blinking cursor + * Move textarea out of the screen to the far left, so that the cursor is not visible. + */ + position: absolute; + opacity: 0; + left: -9999em; + top: 0; + width: 0; + height: 0; + z-index: -10; + /** Prevent wrapping so the IME appears against the textarea at the correct position */ + white-space: nowrap; + overflow: hidden; + resize: none; +} + +.xterm .composition-view { + /* TODO: Composition position got messed up somewhere */ + background: #000; + color: #FFF; + display: none; + position: absolute; + white-space: nowrap; + z-index: 1; +} + +.xterm .composition-view.active { + display: block; +} + +.xterm .xterm-viewport { + /* On OS X this is required in order for the scroll bar to appear fully opaque */ + background-color: #000; + overflow-y: scroll; + cursor: default; +} + +.xterm canvas { + position: absolute; + left: 0; + top: 0; +} + +.xterm .xterm-scroll-area { + visibility: hidden; +} + +.xterm .xterm-char-measure-element { + display: inline-block; + visibility: hidden; + position: absolute; + left: -9999em; +} + +.xterm.enable-mouse-events { + /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */ + cursor: default; +} + +.xterm:not(.enable-mouse-events) { + cursor: text; +} diff --git a/xterm.js/src/xterm.ts b/xterm.js/src/xterm.ts new file mode 100644 index 0000000..6df3a4c --- /dev/null +++ b/xterm.js/src/xterm.ts @@ -0,0 +1,10 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + * + * This file is the entry point for browserify. + */ + +import { Terminal } from './Terminal'; + +module.exports = Terminal; diff --git a/xterm.js/tsconfig.json b/xterm.js/tsconfig.json new file mode 100644 index 0000000..38bfd2f --- /dev/null +++ b/xterm.js/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "rootDir": "src", + "outDir": "lib", + "sourceMap": true, + "removeComments": true + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "src/addons/**/*" + ] +} diff --git a/xterm.js/tslint.json b/xterm.js/tslint.json new file mode 100644 index 0000000..4d4d4aa --- /dev/null +++ b/xterm.js/tslint.json @@ -0,0 +1,62 @@ +{ + "rules": { + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "indent": [ + true, + "spaces" + ], + "typedef": [ + true, + "call-signature", + "parameter" + ], + "eofline": true, + "no-eval": true, + "no-internal-module": true, + "no-trailing-whitespace": true, + "one-variable-per-declaration": [ + true, + true + ], + "no-unsafe-finally": true, + "no-var-keyword": true, + "quotemark": [ + true, + "single" + ], + "semicolon": [ + true, + "always" + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "variable-name": [ + true, + "ban-keywords" + ], + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ] + } +} diff --git a/xterm.js/webpack.config.js b/xterm.js/webpack.config.js new file mode 100644 index 0000000..0c39626 --- /dev/null +++ b/xterm.js/webpack.config.js @@ -0,0 +1,10 @@ +const path = require('path'); + +module.exports = { + entry: './demo/main.js', + output: { + path: path.resolve(__dirname, 'demo/dist'), + filename: 'bundle.js' + }, + devtool: 'source-map' +};