Home

Awesome

@dojo/web-editor

Build Status codecov.io npm version

A package that provides editing and running of Dojo 2 projects in browser.

WARNING This is alpha software. This is not yet production ready, so you should use at your own risk.

Functionality

The web-editor provides three main errors of functionality:

This package is inteded to be integrated into a website which would provide a more rich user interface to allow editing and running the project in a browser. There is a minimal API implemented in examples/index.html which allows the loading of example projects that are included in this package in projects. This example is available at dojo.github.io/web-editor/

project

This is a singleton instance of a class which provides an API to load and manage a project. A project file is a JSON file that conforms to the interface described in ProjectJson which is part of the @dojo/cli-export-project package.

Because of the way the monaco-editor works, you can only have one environment per page, and project needs to interface with this environment to instruct the TypeScript services what is available so the editors and the emit for the project work correctly.

There are several key methods of project:

Usage

Typical usage would be something like this:

import project from '@dojo/web-editor/project';

(async () => {
    await project.load('some.project.json');
    console.log('Loaded!');
})();

Workbench

This is a widget which wraps the other widgets to provide a workbench for editing files and running projects.

The Workbench has a few key properties:

Workbench is a themeable widget, with workbench.root and workbench.filepane being themeable.

Editor

This is a widget which wraps monaco-editor, allowing the editor to seemlessly integrate with the project. It will automatically display files with the appropriate language intellisense as well as the file is edited, changes will automatically be sent to the project to keep it updated.

The Editor has two key properties:

Editor is a themeable widget, with the only themeable class being editor.root.

Usage

Typical usage would be something like this:

import project from '@dojo/web-editor/project';
import Editor from '@dojo/web-editor/Editor';
import { v, w } from '@dojo/widget-core/d';
import Projector from '@dojo/widget-core/mixins/Projector';
import WidgetBase from '@dojo/widget-core/WidgetBase';

(async () => {
    await project.load('some.project.json');

    class App extends WidgetBase {
        render() {
            return v('div', [
                w(Editor, {
                    filename: './src/main.ts'
                })
            ]);
        }
    }

    const projector = new (Projector(App))();
    projector.append();
})();

Runner

A widget runs a program in an iframe. Updating the properties related to the program on the widget will cause it to re-render the program.

The Runner has several key properties which control its behaviour:

Runner is a themeable widget, with the only themeable class being runner.root.

Usage

import { assign } from '@dojo/core/lang';
import project, { Program } from '@dojo/web-editor/project';
import Runner, { RunnerProperties } from '@dojo/web-editor/Runner';
import { v, w } from '@dojo/widget-core/d';
import { WidgetProperties } from '@dojo/widget-core/interfaces';
import Projector from '@dojo/widget-core/mixins/Projector';
import WidgetBase from '@dojo/widget-core/WidgetBase';

interface AppProperties extends WidgetProperties {
    program?: Program
}

(async () => {
    await project.load('some.project.json');

    class App extends WidgetBase<AppProperties> {
        render() {
            return v('div', [
                w(Runner, this.properties.program)
            ]);
        }
    }

    const projector = new (Projector(App))();
    projector.append();

    const program = await project.getProgram();
    project.setProperties({ program });
})();

routing

This module wraps @dojo/routing in a way that works well for the web-editor.

The web-editor allows integration with GitHub's Gists, allowing storage of the project.json in a Gist which can then be used to load the project into the editor.

setPath()

Set the path on the current page. When a project is loaded, this is used to update the path to reflect the Gist's ID.

startGistRouter()

startGistRouter() is function that will configure and start the router, returning a pausable handle. The function takes a single options argument which has two required properties:

Typical usage would look like:

import { startGistRouter } from '@dojo/web-editor/routing';

startGistRouter({
    onGist(request) {
        // request.params.id contains the requested Gist ID
        // so if the project is not loaded, load the project with the supplied ID
    },

    onRoot() {
        // navigation has occured to the root, if the project is not loaded,
        // enable UI elements to allow a user to select a project
    }
});

external/postcss-bundle

In order to properly transpile CSS that is part of a project, the web-editor needs to utilise postcss with additional plugins for this purpose. Because postcss is distributed as a NodeJS package, it is necessary to make this available in the browser with appropriate fills of NodeJS functionality. This is accomplished by creating a WebPack bundle of the modules and exporting the key modules as globals.

This bundle needs to be loaded prior to loading the AMD loader, otherwise there will be conflicts between the WebPack require() and the AMD require(). It should look something like this:

<!DOCTYPE html>
<html><title>Example</title></html>
<body>
    <script src="node_modules/@dojo/web-editor/external/postcss-bundle.js"></script>
    <script src="node_modules/@dojo/web-editor/node_modules/monaco-editor/min/vs/loader.js"></script>
    <script>
        window.MonacoEnvironment = {
            getWorkerUrl: function () {
                return '../worker-proxy.js';
            }
        };

        require.config({
            paths: {
                'vs': 'node_modules/@dojo/web-editor/node_modules/monaco-editor/min/vs',
                '@dojo': 'node_modules/@dojo'
            }
        });

        require([ './example' ], function () {});
    </script>
</body>

Supporting Modules

There are several modules which are used to support the functionality of the web editor.

support/providers/amdRequire

This module is used with @dojo/core/require to make it possible to retrieve inlined resources, like JSON, from a runner application. This will be injected, like the other transpiled modules, which resolve local resources via AMD and pass remote requests to @dojo/core/require/providers/xhr.

support/css

This module provides the transpilation of CSS for a runner application. It provides the ability to run the CSS through CSSNext and also provides the necessary information to allow CSS Modules to work in Dojo 2 applications.

support/DOMParser

A module where the default export is a reference to the global DOMParser.

support/gists

A module that provides tools for working with project.json files that are stored in GitHub Gists.

getById()

An async function that resolves to a description and a URL to a package.json for a given Gist ID.

An example of usage:

import { getById } from '@dojo/web-editor/support/gists';

(async () => {
    const gist = await getById(someId);
    await project.load(gist.projectJson);
})();

getByUsername()

An async function that resolves to an array of descriptions, IDs, and URLs to a package.json files stored in Gists for a given user.

An example of usage:

import { getByUsername } from '@dojo/web-editor/support/gists';

(async () => {
    const gists = await getById(someUsername);
    gists.forEach((gist) => {
        // populate a UI with available Gists
    });
})();

support/json

This module provides the ability to inline JSON to the AMD loader so that local project resources are available to the runner application.

support/postcss, support/postcssCssnext, support/postcssModules

These are modules which export the exposed globals from the postcss-bundle.

support/worker-proxy

This is script which will setup the monaco-editor web workers to be able to provide better performance when editing and running projects. This file should be configured up in the monaco-editor environment before attempting to load the rest of monaco-editor.

For example, you might have something like this in your web-editor page:

<script>
    window.MonacoEnvironment = {
        getWorkerUrl: function () {
            return 'node_modules/@dojo/web-editor/support/worker-proxy.js';
        }
    };
</script>

Installation

The package is typically instlaled using npm. The distrubition though comes with a version of monaco-editor that uses the current version of TypeScript. Therefore it is often better to use that included version than the version that is currently available, as it appears the general avaialable version lags behind in updating.

Licensing Information

This package also includes the following libraries and their dependencies:

© 2017 JS Foundation. New BSD license.