elm-view-engine

View engine allowing rendering of elm views. Express compatible!

View the Project on GitHub OzTK/elm-view-engine

elm-view-engine npm Build Status Coverage Status Known Vulnerabilities

Renders elm views from a directory of elm modules. This can and is meant to be plugged into Express as a template engine.

The 2 simple goals of this project are:

BREAKING CHANGE

Elm views format changed in v2.0! see corresponding section

Getting Started

Prerequisites

Elm needs to be installed either globally or locally in the project.

> npm i -g elm

or

> npm i elm

Installing

> npm i elm-view-engine

Usage

You can use the view engine by itself to being able to render a directory of elm views, or you can plug it in to express as a view engine.

Standalone use

Typescript:

import { configure, Options } from "elm-view-engine";

configure(new Options("path/to/my/views", "path/to/elm/root")).then((engine) => {
  const someContext = {
    arrayOfUsers: [ "Paul", "Jack", "Barbara" ];
  };
  const viewContent = engine.getView("UsersView", someContext);
  // Do something with the html
}));

Javascript:

var eve = require('elm-view-engine');

var options = {
  viewsDirPath: 'path/to/my/views',
  projectRoot: 'path/to/elm/root',
};

eve.configure(options).then((engine) => {
  const someContext = {
    arrayOfUsers: [ 'Paul', 'Jack', 'Barbara' ],
  };
  const viewContent = engine.getView('UsersView', someContext);
  // Do something with the html
}));

Express integration

Just call the configure function passing your express app in the options:

Typescript:

import { configure, Options } from "elm-view-engine";
import * as express from "express";

const app = express();

configure(new Options("path/to/my/views", "path/to/elm/root", app)).then(() => {
  // app template engine is ready
  app.use(...);
}));

Javascript:

var eve = require('elm-view-engine');
var express = require('express');

var app = express();

var options = {
  viewsDirPath: 'path/to/my/views',
  projectRoot: 'path/to/elm/root',
  expressApp: app,
};

eve.configure(options).then(() => {
  // app template engine is ready
  app.use(...);
}));

Views

Your elm views must expose 2 functions with the following signatures:

view : MyContext -> Html MyMsg
context : Json.Decode.Decoder MyContext

If they don’t, views compilation will fail.

view : () -> Html Never view _ = – Code for your view

* `context` returns a decoder for the context that will deserialize the json context internally to the engine
* Passing an invalid context when requesting a view will result in an error from the engine

##### Example

A view with a simple context:

```elm
module Greeter exposing (view, context)

import Html exposing (Html, h1, div, text)
import Json.Encode
import Json.Decode exposing (decodeValue, string)
import Json.Decode.Pipeline exposing (decode, required)


-- Model


type alias SimpleContext =
    { simpleName : String }


context : Json.Decode.Decoder SimpleContext
context =
    decode SimpleContext
        |> required "simpleName" string



-- View


view : SimpleContext -> Html Never
view ctx =
    div
        []
        [ h1 []
            [ text ("Hello " ++ ctx.simpleName ++ "!")
            ]
        ]

Pre-compiling

The views get compiled once when calling configure(). They are then cached and reused. This causes 2 inconveniences:

To overcome this, it is possible to compile your views with the CLI by using the elm-view-engine command. It will compile the views right away, and can be done before or after the server has started. The views can now be compiled beforehand or during server execution for development (See example for integration in npm scripts).

Running elm-view-engine -h gives more info about the command.

Running the tests

Just git clone https://github.com/OzTK/elm-view-engine and run the npm test command from the root of the project. You can check the coverage by running npm run coverage:local.

Built With

Because of the dynamic nature of the project, I had to generate elm code (the template for the module is src/MainTemplate.elm). I also needed to compile this generated elm code on the fly (when you call configure()) and render elm views into html strings. I relied on the following libraries for this purpose:

Contributing

Please feel free to open issues for any concerns. PRs welcome!