Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: getting started #213

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions docs/_css/site.less
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ code {
}

pre code, code {
overflow-x: auto;
font-family: "ubuntu-mono";
}

Expand Down Expand Up @@ -120,12 +121,23 @@ hr {
}
}

/* API */
/* GETTING STARTED */

.getting-started {
nav a.link-getting-started {
.navselected();
}
}

/* API */
.api {
nav a.api {
nav a.link-api {
.navselected();
}
}

/* API and GETTING-STARED shared */
.api-shared {
.content-wrapper {
section.content {
background: #fff;
Expand Down Expand Up @@ -169,7 +181,7 @@ body.playground {
top: 0px; left: 0px;
width: 100%; height: 100%;

nav a.playground {
nav a.link-playground {
.navselected();
}

Expand Down
5 changes: 3 additions & 2 deletions docs/_layouts/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ <h1><a href="/">
</a></h1>
</div>
<nav>
<a class="api" href="/api/">Api</a>
<a class="playground" href="/playground/">Playground</a>
<a class="link-getting-started" href="/start/">Getting started</a>
<a class="link-api" href="/api/">API</a>
<a class="link-playground" href="/playground/">Playground</a>
<a href="http://github.com/ariatemplates/hashspace">Github</a>
<a class="download button green" target="_blank" href="https://github.com/ariatemplates/hashspace/releases">Download</a>
</nav>
Expand Down
2 changes: 1 addition & 1 deletion docs/api/index.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
title: API Reference
cssclass: api
cssclass: api-shared api
mappings:
CONTENT_BEGIN: <article class="columns"><div>
CONTENT_END: </div></article>
Expand Down
261 changes: 261 additions & 0 deletions docs/start/explained/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
title: Getting started
cssclass: api-shared getting-started
mappings:
CONTENT_BEGIN: <article class="columns"><div>
CONTENT_END: </div></article>
---

[CONTENT_BEGIN]

# Getting started with Hashspace: explained

To get started with Hashspace, you have two options: either compile the Hashspace files (`*.hsp`)
to JavaScript on the server side (during build time), or compile them dynamically in the browser
(useful for debugging and rapid prototyping).

The examples on this page assume that you have [Node](http://nodejs.org) platform installed on your machine,
though this is not necessary for in-browser template interpretation.

## On-the-fly (in-browser) compilation

Let's first have a look with on-the-fly compilation. This is a good option if you're just starting
development and care more about developer's productivity than page load performance.

If you want to have on-the-fly in-browser compilation, you may go with Hashspace + NoderJS duo.

First, let's create a simple HSP file and a controller:

#### `hello.hsp`

````
var HelloCtrl = require("./HelloCtrl");

{template Hello using ctrl:HelloCtrl}
<p>Hello, {ctrl.name}!</p>

<input model="{ctrl.name}">
<button onclick="{ctrl.clear()}">Clear</button>
{/template}

module.exports = Hello;
```

#### `HelloCtrl.js`

```
var klass = require("hsp/klass");

var HelloCtrl = klass({
// declaring "name" attribute so that we can pass it
// when instantiating a template via `Hello({name:"World"})`
attributes: {
"name" : { type : "string" }
},
clear : function () {
this.name = "";
}
});

module.exports = HelloCtrl;
```

Now we need an HTML file that will take care of rendering the template.

- First (1), we need to load noderJS -- the CommonJS loader necessary for loading our
modules -- and tell it via the configuration parameter that whenever it encounters an HTTP request for:

- `*.hsp` file, then the downloaded file should be
additionally **compiled in the browser** by an appropriate compiler module
(see `preprocessors` config) to the pure JavaScript code that the browser understands.

- `*.js` file, then the downloaded file should be **rewritten with Hashspace transpiler**:
all occurrences of code like `foo.bar = 42` will be rewritten to `$set(foo, "bar", 42)`,
so that Hashspace automatic data bindings work correctly (actually, this step is not
needed -- but otherwise you'd have to remember to use `$set` yourself in all JS code,
which can be tedious and error-prone).

- Then, we need to load Hashspace runtime and the mentioned Hashspace in-browser compiler (2).

- Next, we need an HTML element in which our template will be rendered. In (3), we're creating
a `<div id="output" />`.

- Finally (4), we're ready to start our application: create a `<script type="application/x-noder">` that will
be executed via noderJS, which fetches and evaluates the `hello.hsp` template. The HSP file exports
a `Hello` template, which we then instantiate and call its `render` method which renders its HTML output
in an HTML element with given id (`output` in this example).

#### `index.htm` (using source HSP files)

```
<!DOCTYPE html>
<html>
<head>
<!-- 1: load noderJS with appropriate config -->
<script src="http://noder-js.ariatemplates.com/dist/v1.5.0/noder.dev.js" type="text/javascript">
{
packaging: {
preprocessors: [{
pattern: /\.hsp$/,
module: "hsp/compiler/compile"
}, {
pattern: /\.js$/,
module: "hsp/transpiler/transpile"
}]
}
}
</script>

<!-- 2: load Hashspace and Hashspace compiler -->
<script src="http://hashspace.ariatemplates.com/dist/0.0.4/hashspace-noder.js" type="text/javascript"></script>
<script src="http://hashspace.ariatemplates.com/dist/0.0.4/hashspace-noder-compiler.js" type="text/javascript"></script>

<!-- 4: ready to load our HSP file! -->
<script type="application/x-noder">
var Hello = require('hello.hsp');
Hello({name:"World"}).render("output");
</script>
</head>
<body>
<!-- 3: the output element -->
<div id="output"></div>
</body>
</html>
```

Now to see the effects of our effort, we just need to start an HTTP server
(since in most modern browsers, `XMLHttpRequest`s from `file://` protocol are disabled for security reasons).

For instance, we may use a simple zero-configuration `http-server` module from npm.

- `$ npm install -g http-server`
- `$ cd /path/to/my/app`
- `$ http-server`
- navigate to `http://localhost:8080/index.htm` in a browser.

## Server-side compilation

When your application is getting mature, it's better to precompile Hashspace templates
at build time, so that the web browser has less work to do and, in turn, renders them faster.

We'll consider the two sample files presented earlier. We'll just slightly tweak the HTML file,
and introduce compiler & transpiler scripts.

To get the possibility to use the compiler and transpiler, we need to install Hashspace:

- `$ npm install hashspace`

If you prefer bare-metal solutions, you may use essentially the following one-liners
of NodeJS code to transform a piece of Hashspace to JavaScript:

```
var compiledHS = require('hashspace').compiler.compile(inputHSCode, inputHSFileName).code;
```
```
var transpiledJS = require('hashspace/hsp/transpiler/transpile')(inputJSCode, inputJSFileName);
```

In a more real-world example we would read files from disk and output the transformed ones
to disk as well, in a separate directory. We could do this with the following NodeJS program:

#### `compile.js`

```
var fs = require('fs');
var hscompiler = require('hashspace').compiler;

var cfg = {
inputFile : "src/hello.hsp",
outputFile : "out/hello.hsp.js"
};

var fileContents = fs.readFileSync(cfg.inputFile, "utf-8");
var output = hscompiler.compile(fileContents, cfg.inputFile);
if (!fs.existsSync("out")) {
fs.mkdirSync("out");
}
fs.writeFileSync(cfg.outputFile, output.code);
```

A similar program to transpile JS to `$set`-syntax:

#### `transpile.js`

```
var fs = require('fs');
var transpile = require('hashspace/hsp/transpiler/transpile');

var cfg = {
inputFile : "src/HelloCtrl.js",
outputFile : "out/HelloCtrl.js"
};

var fileContents = fs.readFileSync(cfg.inputFile, "utf-8");
var output = transpile(fileContents, cfg.inputFile);
if (!fs.existsSync("out")) {
fs.mkdirSync("out");
}
fs.writeFileSync(cfg.outputFile, output);
```

Running the following command will now produce the output files:

- `$ node compile`
- `$ node transpile`

Two remarks:

- We named the output HSP file with `.js` extension since it's a valid JS file, though actually
we may name it whatever we like, e.g. just keep the `.hsp` extension.
- Of course those are a simple examples compiling one hardcoded file at a time. In your script you'd
have to traverse a set of input files yourself, or use existing tools (read further).

Finally, we need a proper `index.htm` file. However this time we don't need to include a compiler script
nor to set-up NoderJS's preprocessors. Apart from that, we need to, obviously, require a compiled file.

#### `index.htm` (using compiled HSP files)

```
<!DOCTYPE html>
<html>
<head>
<!-- 1: load noderJS -->
<script src="http://noder-js.ariatemplates.com/dist/v1.5.0/noder.dev.js" type="text/javascript"></script>

<!-- 2: load Hashspace -->
<script src="http://hashspace.ariatemplates.com/dist/0.0.4/hashspace-noder.js" type="text/javascript"></script>

<!-- 4: ready to load our compiled HSP file! -->
<script type="application/x-noder">
var Hello = require('out/hello.hsp.js');
Hello({name:"World"}).render("output");
</script>
</head>
<body>
<!-- 3: the output element -->
<div id="output"></div>
</body>
</html>
```

As suggested earlier, we can now

- run `$ http-server`
- and navigate to `http://localhost:8080/index.htm` in a browser to see the output.

### GulpJS packages

If you're using [gulpjs](http://gulpjs.com/), you may use dedicated tasks for compiling Hashspace files.
You can have a look at a
[sample Hashspace Hello World application with Gulp setup](https://github.com/PK1A/hsp-hello-gulp)
which makes use of `gulp-hsp-compiler` and `gulp-hsp-transpiler` npm packages.

## Appendix: where to get Hashspace and noderJS builds

In the above examples, we've used certain released versions of Hashspace and noder.
You can see the available versions under the following URLs:

- [Hashspace releases](https://github.com/ariatemplates/hashspace/tree/gh-pages/dist/)
- [noderJS releases](https://github.com/ariatemplates/noder-js/tree/gh-pages/dist/)

If you want to use the latest improvements in not-yet-released code, you may use SNAPSHOT versions.

Loading