Sky
===

Sky is an experiment in building a UI framework for Mojo.  The approach we're
exploring is to create a layered framework based around a retained hierarchy of
semantic elements.  We're experimenting with different ideas and exploring
various approaches, many of which won't work and will need to be discarded, but,
if we're lucky, some of which might turn out to be useful.

Sky has three layers, each of which also adds progressively more opinion.  At
the lowest layer, Sky contains a rendering engine that parses markup, executes
script, and applies styling information.  Layered above the engine is a
collection of components that define the interactive behavior of a suite of
widgets, such as input fields, buttons, and menus.  Above the widget layer is a
theme layer that gives each widget a concrete visual and interactive design.

Elements
--------

The Sky engine contains [a handful of primitive elements](specs/markup.md) and the tools with which
to create custom elements.  The following elements are built into the engine:

 - ``script``: Executes script
 - ``style``: Defines style rules
 - ``import``: Loads a module
 - ``iframe``: Embeds another Mojo application
 - ``template``: Captures descendants for use as a template
 - ``content``: Visually projects descendents of the shadow host
 - ``shadow``: Visually projects older shadow roots of the shadow host
 - ``img``: Displays an image
 - ``div``: Neutral element for hooking styles in shadow trees
 - ``span``: Neutral element for hooking styles in shadow trees
 - ``a``: Links to another Mojo application
 - ``title``: Briefly describes the current application state to the user
 - ``t``: Preserve whitespace (by default, whitespace nodes are dropped)
 - ``error``: Represents a parse error

### Additional Elements ###

In addition to the built-in elements, frameworks and applications can define
custom elements.  The Sky framework contains a number of general-purpose
elements, including ``input``, ``button``, ``menu``, ``toolbar``, ``video``, and
``dialog``.  However, developers are free to implement their own input fields,
buttons, menus, toolbars, videos, or dialogs with access to all the same engine
features as the frame because the framework does not occupy a privileged
position in Sky.

### Custom Layout ###

TODO: Describe the approach for customizing layout.

### Custom Painting ###

TODO: Describe the approach for customizing painting.

Modules
-------

Sky applications consist of a collection of modules.  Each module can describe
its dependencies, register custom elements, and export objects for use in other
modules.

Below is a sketch of a typical module.  The first ``import`` element imports the
Sky framework, which defines the ``sky-element`` element.  This module then uses
``sky-element`` to define another element, ``my-element``. The second ``import``
element imports another module and gives it the name ``foo`` within this module.
For example, the ``AnnualReport`` constructor uses the ``BalanceSheet`` class
exported by that module.

```html
SKY MODULE
<import src=”/sky/framework” />
<import src=”/another/module.sky” as=”foo” />
<sky-element name=”my-element”>
class extends SkyElement {
  constructor () {
    this.addEventListener('click', (event) => this.updateTime());
    this.shadowRoot.appendChild('Click to show the time');
  }
  updateTime() {
    this.shadowRoot.firstChild.replaceWith(new Date());
  }
}
</sky-element>
<script>
class AnnualReport {
  constructor(bar) {
    this.sheet = new foo.BalanceSheet(bar);
  }
  frobinate() {
    this.sheet.balance();
  }
}

function mult(x, y) {
  return x * y;
}

function multiplyByTwo(x) {
  return mult(x, 2);
}

module.exports = {
  AnnualReport: AnnualReport,
  multiplyByTwo: multiplyByTwo,
};
</script>
```

The script definitions are local to each module and cannot be referenced by
other modules unless exported.  For example, the ``mult`` function is private to
this module whereas the ``multiplyByTwo`` function can be used by other modules
because it is exported.  Similarly, this module exports the ``AnnualReport``
class.

Services
--------

Sky applications can access Mojo services and can provide services to other Mojo
applications.  For example, Sky applications can access the network using Mojo's
``network_service``.  Typically, however, Sky applications access services via
frameworks that provide idiomatic interfaces to the underlying Mojo services.
These idiomatic interfaces are layered on top of the underlying Mojo service,
and developers are free to use the underlying service directly.

As an example, the following is a sketch of a module that wraps Mojo's
``network_service`` in a simpler functional interface:

```html
SKY MODULE
<import src=”mojo:shell” as=”shell” />
<import src="/mojo/network/network_service.mojom.sky" as="net" />
<import src="/mojo/network/url_loader.mojom.sky" as="loader" />
<script>
module.exports = function fetch(url) {
  var networkService = shell.connectToService(
      "mojo:network_service", net.NetworkService);
  var request = new loader.URLRequest({
      url: url, method: "GET", auto_follow_redirects: true});
  var urlLoader = networkService.createURLLoader();
  return urlLoader.start(request).then(function(response) {
    if (response.status_code == 200)
      return response.body;
    else
      throw response;
  });
};
</script>
```

Notice that the ``shell`` module is built-in and provides access to the
underlying Mojo fabric but the ``net`` and ``loader`` modules run inside Sky and
encode and decode messages sent over Mojo pipes.

Specifications
--------------

We're documenting Sky with a [set of technical specifications](specs) that
define precisely the behavior of the engine.  Currently both the implementation
and the specification are in flux, but hopefully they'll converge over time.

Contributing
------------

Instructions for building and testing Sky are contained in [HACKING.md](HACKING.md). For
coordination, we use the ``#mojo`` IRC channel on
[Freenode](https://freenode.net/).

History
-------
Sky started from the Blink codebase r181355:
http://blink.lc/blink/tree/?id=086acdd04cbe6fcb89b2fc6bd438fb8819a26776
