Giter Site home page Giter Site logo

avaloniarider's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

avaloniarider's Issues

Crossplatform build

Users should be able to build the plugin on Linux, Windows and macOS, and CI should check the build on these OSs.

Failed to build on Win

Log:

C:\Users\SKProCH\Downloads\AvaloniaRider>gradlew buildPlugin
Starting a Gradle Daemon, 1 incompatible and 1 stopped Daemons could not be reused, use --status for details

> Task :rdgen
Reading hash from build\rdgen\rider\.rdgen
Hashes are different at key 'file: C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\com.jetbrains.rd\rd-gen\0.193.146\38e03009032d0ea8ff19183cb90afdca3e6f09e3\rd-gen-0.193.146.jar', oldHash: , newHash:2020-02-10_13:22:50.188
Temporary folder created: C:\Users\SKProCH\AppData\Local\Temp\rdgen-17510054252182648603
Searching for Kotlin compiler
Compiling sources from 'C:\Users\SKProCH\Downloads\AvaloniaRider\protocol\src\main\kotlin\model\rider' to 'C:\Users\SKProCH\AppData\Local\Temp\rdgen-17510054252182648603'
User classpath: 'C:\Users\SKProCH\Downloads\AvaloniaRider\build\riderRD-2019.3.1\lib\rd\rider-model.jar'
Rdgen default classpath: 'C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\com.jetbrains.rd\rd-gen\0.193.146\38e03009032d0ea8ff19183cb90afdca3e6f09e3\rd-gen-0.193.146.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk8\1.3.50\bf65725d4ae2cf00010d84e945fcbc201f590e11\kotlin-stdlib-jdk8-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler\1.3.50\ec5559072cc613b67b47ae33c4936fe00a6e356f\kotlin-compiler-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk7\1.3.50\50ad05ea1c2595fb31b800e76db464d08d599af3\kotlin-stdlib-jdk7-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-scripting-jvm\1.3.61\b9311f022363534f8776e4392aa9c4f4d5a62a44\kotlin-scripting-jvm-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-scripting-common\1.3.61\169747d90a1ccdd30b25c381a06bee3fe579bf2\kotlin-scripting-common-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler-embeddable\1.3.61\c35c0833d5a1e3d229359758482c480306724618\kotlin-compiler-embeddable-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-reflect\1.3.61\2e07c9a84c9e118efb70eede7e579fd663932122\kotlin-reflect-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib\1.3.61\4702105e97f7396ae41b113fdbdc180ec1eb1e36\kotlin-stdlib-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-common\1.3.61\65abb71d5afb850b68be03987b08e2c864ca3110\kotlin-stdlib-common-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-script-runtime\1.3.61\e5feb39c8de63dcbdc1154b34ca4413874231605\kotlin-script-runtime-1.3.61.jar'
Resulting kotlinc classpath: 'C:\Users\SKProCH\Downloads\AvaloniaRider\build\riderRD-2019.3.1\lib\rd\rider-model.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\com.jetbrains.rd\rd-gen\0.193.146\38e03009032d0ea8ff19183cb90afdca3e6f09e3\rd-gen-0.193.146.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk8\1.3.50\bf65725d4ae2cf00010d84e945fcbc201f590e11\kotlin-stdlib-jdk8-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler\1.3.50\ec5559072cc613b67b47ae33c4936fe00a6e356f\kotlin-compiler-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk7\1.3.50\50ad05ea1c2595fb31b800e76db464d08d599af3\kotlin-stdlib-jdk7-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-scripting-jvm\1.3.61\b9311f022363534f8776e4392aa9c4f4d5a62a44\kotlin-scripting-jvm-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-scripting-common\1.3.61\169747d90a1ccdd30b25c381a06bee3fe579bf2\kotlin-scripting-common-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler-embeddable\1.3.61\c35c0833d5a1e3d229359758482c480306724618\kotlin-compiler-embeddable-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-reflect\1.3.61\2e07c9a84c9e118efb70eede7e579fd663932122\kotlin-reflect-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib\1.3.61\4702105e97f7396ae41b113fdbdc180ec1eb1e36\kotlin-stdlib-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-common\1.3.61\65abb71d5afb850b68be03987b08e2c864ca3110\kotlin-stdlib-common-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-script-runtime\1.3.61\e5feb39c8de63dcbdc1154b34ca4413874231605\kotlin-script-runtime-1.3.61.jar'
kotlinc -cp C:\Users\SKProCH\Downloads\AvaloniaRider\build\riderRD-2019.3.1\lib\rd\rider-model.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\com.jetbrains.rd\rd-gen\0.193.146\38e03009032d0ea8ff19183cb90afdca3e6f09e3\rd-gen-0.193.146.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk8\1.3.50\bf65725d4ae2cf00010d84e945fcbc201f590e11\kotlin-stdlib-jdk8-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler\1.3.50\ec5559072cc613b67b47ae33c4936fe00a6e356f\kotlin-compiler-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk7\1.3.50\50ad05ea1c2595fb31b800e76db464d08d599af3\kotlin-stdlib-jdk7-1.3.50.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-scripting-jvm\1.3.61\b9311f022363534f8776e4392aa9c4f4d5a62a44\kotlin-scripting-jvm-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-scripting-common\1.3.61\169747d90a1ccdd30b25c381a06bee3fe579bf2\kotlin-scripting-common-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-compiler-embeddable\1.3.61\c35c0833d5a1e3d229359758482c480306724618\kotlin-compiler-embeddable-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-reflect\1.3.61\2e07c9a84c9e118efb70eede7e579fd663932122\kotlin-reflect-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib\1.3.61\4702105e97f7396ae41b113fdbdc180ec1eb1e36\kotlin-stdlib-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-common\1.3.61\65abb71d5afb850b68be03987b08e2c864ca3110\kotlin-stdlib-common-1.3.61.jar;C:\Users\SKProCH\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-script-runtime\1.3.61\e5feb39c8de63dcbdc1154b34ca4413874231605\kotlin-script-runtime-1.3.61.jar -d C:\Users\SKProCH\AppData\Local\Temp\rdgen-17510054252182648603 -jvm-target 1.8 C:\Users\SKProCH\Downloads\AvaloniaRider\protocol\src\main\kotlin\model\rider
warning: unable to find kotlin-stdlib.jar in the Kotlin home directory. Pass either '-no-stdlib' to prevent adding it to the classpath, or the correct '-kotlin-home'
warning: unable to find kotlin-script-runtime.jar in the Kotlin home directory. Pass either '-no-stdlib' to prevent adding it to the classpath, or the correct '-kotlin-home'
warning: unable to find kotlin-reflect.jar in the Kotlin home directory. Pass either '-no-reflect' or '-no-stdlib' to prevent adding it to the classpath, or the correct '-kotlin-home'
Compilation finished in 10734 ms
Loading compiled classes from 'file:/C:/Users/SKProCH/AppData/Local/Temp/rdgen-17510054252182648603/, file:/C:/Users/SKProCH/Downloads/AvaloniaRider/build/riderRD-2019.3.1/lib/rd/rider-model.jar'

RdGen model generator started
Searching classes with namespace prefixes: 'model.rider'
Regex for filtering generators: '.*'
Found 2 gradle generators
3 classes found
1 toplevel class found

Toplevels to generate:
  singleton `AvaloniaRiderModel` :> concrete_class `Solution` :> singleton `SolutionModel` :> root `IdeRoot`

Collecting generators (filtering generator's `javaClass.simpleName` by regex '.*'):
  0 hardcoded generator(s) -- specified directly in 'Root' constructor
  2 gradle generator(s)    -- specified in gradle's rdgen plugin 'rdgen { generator { ...} }' sections
  0 external generator(s)  -- specified by extending kotlin object from class GenerationUnit

++  MATCHED TO  ++ 'root `IdeRoot`' + Kotlin11(AsIs, "com.jetbrains.rider.model", 'C:\Users\SKProCH\Downloads\AvaloniaRider\src\rider\main\kotlin\avaloniarider\model')
++  MATCHED TO  ++ 'root `IdeRoot`' + CSharp50(Reversed, "JetBrains.Rider.Model", 'C:\Users\SKProCH\Downloads\AvaloniaRider\src\dotnet\AvaloniaRider.Plugin\Rider\Model')

After filtering 2 generator(s) to run
Invoke CSharp50(Reversed, "JetBrains.Rider.Model", 'C:\Users\SKProCH\Downloads\AvaloniaRider\src\dotnet\AvaloniaRider.Plugin\Rider\Model') on root `IdeRoot`, clearFolder=false
Invoke Kotlin11(AsIs, "com.jetbrains.rider.model", 'C:\Users\SKProCH\Downloads\AvaloniaRider\src\rider\main\kotlin\avaloniarider\model') on root `IdeRoot`, clearFolder=false
Generation finished in 1048 ms
Storing hash into 'build\rdgen\rider\.rdgen'

> Task :rdgen FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':rdgen'.
> java.io.FileNotFoundException: build\rdgen\rider\.rdgen (╤шёЄхьх эх єфрхЄё  эрщЄш єърчрээ√щ яєЄ№)

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.1.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD FAILED in 6m 34s
1 actionable task: 1 executed```

Render preview for non-runnable assemblies

Currently, when rendering a preview, we rely on AssemblyName.deps.json and AssemblyName.runtimeconfig.json being available for the assembly containing the XAML file in question. These files aren't available for non-runnable assemblies in .NET Core, so the preview won't work.

For controls in such assemblies, we should provide a runnable project selector: filter only the runnable projects that depend on the current assembly, and preselect one of them by default.

If no such project exists, then we won't be able to show a preview.

No output in preview window on MacOS

After installing the plugin in rider through the Preferencers->Plugin panel and restart the IDE I see how when selecting a xaml file a panel appears to the right of the xml file but nothing is shown.

This is the plugin installed:
imagen

And this the empty panel:

imagen

Is there anything I can do to fix this?

Update the build script to use Kotlin

Newer Gradle versions allow to use Kotlin instead of Groovy which should dramatically improve the painful build scripting experience. I think we should consider upgrading the build script.

Refactor the start action

Right now, StartAvaloniaPreviewerAction is a god-file, because it includes all sorts of stuff, from GUI / terminal management to connection management.

Extract the stuff to a proper host and stop holding everything in an action file.

Don't forget to implement Disposable and shut off the socket connections on component dispose.

Show the previewer in the same tab as content

We should add a switcher (like the one Rider have for Windows Forms, or markdown-navigator has for the Markdown files) that will allow the user to switch between source/preview, or even view them both simultaneously.

Use Gradle JVM Wrapper

As many people who want to build the plugin don't usually do JVM development, we could benefit from automated JVM installation using the gradle-jvm-wrapper.

I still investigate if it will work well for all of our users, and want to make its usage optional (but enabled by default). We'll see about that.

Black square shown for some frames

Sometimes, when editing a simple XAML document, preview loads a black square instead of some frames. Closer inspection shows that it seemingly receives this black square from an Avalonia previewer process. Further investigation is required.

Also, check if the web previewer has the same problem.

Make Rider understand Avalonia XAML

Would it be possible to make rider understand the non-standard XAML syntax that Avalonia uses? For example the control binding syntax that uses a #number sign for referencing other controls. Or the dollar sign.

Are there any plans to implement this, or is it outside the scope of this project?

Add .paml and .axaml file type support

These file types are ordinary XAML but with another extension, .paml for Perspex compatibility, and .axaml for better VS interop (.paml is supported from Avalonia 0.3, and .axaml is likely to be included soon).

We should support both of them, too.

WebView-based approach

Here's a new plan that should help us to produce a more light implementation in terms of code:

  1. Embed the web view (JavaFX one for now) into the preview window
  2. Use this on the backend
  3. Direct the web view to the server, and that's it: it should start work immediately

Render method abstraction

Currently, we already support the basic BSON rendering (bitmaps passed via BSON), and there're plans to add HTTP/WebView-based renderer, see #14.

I've decided to abstract these methods and support both of them (since HTTP support seems to not be merged yet into Avalonia main code base).

Web preview: add Browse button

If the web previewer is enabled, then we should add the Browse button somewhere into the preview editor UI, so the user could view/debug the session in their browser.

Templates

<UserControl xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
             x:Class="AvaloniaAppTemplate.Namespace.NewUserControl">
  Welcome to Avalonia!
</UserControl>

usercontrol template

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="AvaloniaAppTemplate.Namespace.NewWindow"
        Title="AvaloniaAppTemplate">
  Welcome to Avalonia!
</Window>

window template

<Styles xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <Style Selector="Window">
                <Setter Property="Background" Value="#FF303030"/>
        </Style>       
</Styles>

avalonia has no template for styles, but it's very useful

Migrate to JCEF instead of JavaFX browser control

Since JavaFX is being obsoleted as an IntelliJ component, and JCEF, on the other hand, being included into it by default, we'll have to migrate from JavaFX to JCEF for the plugin version targeting Rider 2020.2+.

TODO:

  • remove the JavaFX plugin requirement from the README
  • remove the JavaFX plugin requirement from the plugin.xml
  • remove the JavaFX plugin requirement from the build.gradle
  • remove/fix all the associated TODOs in code

Build failed on Mac

Task :compileDotNet FAILED

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':compileDotNet'.

A problem occurred starting process 'command 'powershell''

"Cannot copy assembly" error on build when previewer is open

  1. Build an assembly
  2. Open a previewer process for any view inside of the assembly
  3. While the previewer tab os open (even in background), try to rebuild the assembly

Expected result: the assembly should be rebvuils successfully, the previewer should reconnect (?)
Actual result: the assembly cannot be rebuilt due to "Cannot copy assembly" error (because it is locked by the previewer process)

Enable XAML support in `<AvaloniaResource>`

Avalonia suggests to mark XAML files in the project as <AvaloniaResource>. Currently, XAML support is disabled in such project items. It should be enabled.

Note for implementors: override XamlProjectFileLanguageService.GetPsiLanguageType to return XamlLanguage.Instance in cases when projectFile.Properties.GetBuildActions().Any(ba => ba.[IsAvaloniaResource]). Please contact me in case you, the implementor, is not me.

Possibly only Linux is affected by this issue.

Move the logic to the backend

To make the plugin more approachable for .NET developers, I've decided that we have to move most of the logic to the backend. Frontend part should only handle the logic we completely cannot control on the backend.

Show previewer status and errors in the preview tab

Currently, if the markup has any errors reported by the preview process, nothing happens.

We should handle the errors received from the previewer, and show them in the previewer tab in the editor.

Also, previewer status (connecting/ready/terminated) should be shown, too.

Let's also allow to restart the previewer in case it was terminated (the same as our Windows Forms designer currently allows).

See this code:

// TODO[F]: Handle controller.status and controller.errorMessage

message.error?.let {
logger.warn { "Error from UpdateXamlResultMessage: $it" }
}

// TODO[F]: Catch that in the session controller layer and show a notification

More performant/smart image rendering

Current approach to the image rendering in the BSON renderer is rather suboptimal:

  1. We create a new BufferedImage instance per each frame
  2. Whenever we need to update the image, we use a simple loop over all the received image pixels

This needs to be redesigned with more performant and proper approach. See these pieces of code:

controller.requestViewportResize.advise(lifetime) {
// TODO[F]: Calculate UI scale
}

val image = UIUtil.createImage(this, frame.width, frame.height, BufferedImage.TYPE_INT_RGB)
image.renderFrame(frame)
content.icon = ImageIcon(image) // TODO[F]: Find a clever way to update that

// TODO[F]: This is very suboptimal
private fun BufferedImage.fillWithColor(color: Color) {
for (y in 0 until height) {
for (x in 0 until width) {
setRGB(x, y, color.rgb)
}
}
}

// TODO[F]: This is very suboptimal
fun BufferedImage.renderFrame(frame: FrameMessage) {
this.fillWithColor(Color.WHITE)
for (y in 0 until frame.height) {
for (x in 0 until frame.width) {
val pixelIndex = y * frame.width * 4 + x * 4 // 4 bytes per px
val bytes = frame.data.slice(pixelIndex..pixelIndex + 3)
val color = Color(fromByte(bytes[0]), fromByte(bytes[1]), fromByte(bytes[2]))
setRGB(x, y, color.rgb)
}
}
}

More direct file upload from CI

Currently, our CI includes an artifact named distribution.zip, which, in turn, contains a file avaloniarider-1.3.3.7.zip.

I think we could improve this workflow by providing a direct upload of avaloniarider-1.3.3.7.zip. upload-artifact@v2 should support this.

Previewer window update (BSON renderer)

Previewer window should automatically update on source changes.

Right now, it doesn't do that, and for some reason it gets cleared on file save and/or window resize.

I believe this was working and got broken in subsequent updates, so it's just a but that should be fixed.

Avalonia file templates

We should add templates for various Avalonia-related entities:

  • Window
  • UserControl
  • Styles

These entities should generate <AvaloniaResource> item in the project file. (not sure it's possible to do with Rider's file template mechanism right now, but I'm sure we could invent a clever workaround)

Investigate cache issues on macOS

Currently the caches on macOS are too big to be uploaded, but they really shouldn't be that huge (several GiB each). Need to investigate.

Bad FPS for AvaloniaRemote previewer

To test, add this style:

<Window.Styles>
    <Style Selector="Canvas">
    <Style.Animations>
      <Animation Duration="0:0:1"
                     Easing="QuadraticEaseInOut"
                     IterationCount="Infinite">
            <KeyFrame Cue="50%">
              <Setter Property="ScaleTransform.ScaleX" Value="0.8"/>
              <Setter Property="ScaleTransform.ScaleY" Value="0.8"/>
              <Setter Property="RotateTransform.Angle" Value="150"/>
            </KeyFrame>
          </Animation>
     </Style.Animations>
  </Style>
</Window.Styles>

and apply to any XAML element.

While web previewer draws this animation nicely, AvaloniaRemote one gives about 5 FPS.

Probably caused by #40.

Allow to use horizontal separator in preview mode

Currently, in scope of #17, I'm planning to reuse IDEA-based two-panel previewer, which is very primitive. It doesn't allow to separate editor and previewer by a horizontal separator, only vertical one is available.

We should enable horizontal separator, make it default and configurable.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.