Home

Awesome

The Merlin JS framework

A functional JS framework that values elegance, simplicity and minimalism.

Demo License: MIT GitHub Tag bundlejs

State Management + vDom + Template Engine + SPA Router = ❤️

❤️ Features

💡 Showcase

Demo

<!DOCTYPE html>
<html>
  <head>
    <title>Todo - The Merlin JS framework</title>
  </head>
  <body>
    <main>
      <h1>To do list</h1>
      <input type="text" value:="value" oninput:="NewValue">
      <ul>
        <li each:="todos" text:></li>
      </ul>
      <button onclick:="AddTodo">New!</button>
    </main>
    <script type="module">
      import {app} from "https://cdn.jsdelivr.net/gh/marcodpt/merlin/index.min.js"

      app({
        node: document.body.querySelector('main'),
        init: {
          value: '',
          todos: []
        },
        register: update => ({
          NewValue: ev => update(state => ({
            ...state,
            value: ev.target.value
          })),
          AddTodo: () => update(({todos, value}) => ({
            todos: todos.concat(value),
            value: ''
          }))
        }),
        view: (state, events) => ({
          ...state,
          ...events
        })
      })
    </script>
  </body>
</html>

💯 Examples

📖 API

Merlin uses Tint as its template engine, you should read the docs for a complete reference.

app({node, template?, view?, init, register}) => stop

node: DOM Node

Where to mount the app.

template: Dom Node

An optional template to render, if nothing is passed the node itself will be used.

view: (state, events) => data

Exactly as defined in Ring.

The only exception is that it returns data that will be used for Tint to render the page, if not passed the unmodified state will be returned to Tint.

init: _

Exactly as defined in Ring.

The initial state of the app. It can be any type of data.

register: (update, dispatch) => events

Exactly as defined in Ring.

It is called before initializing the app returning the registered events.

stop: () => ()

Exactly as defined in Ring.

Returns a function that stops the app.

spa({node, routes, plugins?}) => stop

node: DOM Node

Where to mount the spa.

routes: {route: {template?, init?, view?, register?}}

route: string

Exactly as defined in Wand.

Accepts * to match any path and :param to declare variable.

template: Dom Node

A template to be rendered on the route, if nothing is passed it will use the original content of the node.

init: routeData => state

An optional function that will be called every time the route is started, returning the initial state. If not passed, Params from routeData will be used as the initial state.

view, register

Exactly as defined in app

plugins: [routeData => ()]

Exactly as defined in Wand.

An optional array of plugins, which are executed sequentially with each route change and which can modify the routeData.

stop: () => ()

Exactly as defined in Wand.

Returns a function that stops the spa.

routeData {url, route, path, Params, query, Query}

Exactly as defined in Wand.

Plugins can introduce new properties or change existing ones.

url: string

The url as it was passed.

route: string

The route that matched as declared.

path: string

The part of the url before the ?.

Params: object

Object containing the variables declared in the route with the associated values in the current path.

query: string

The part of url after the ?.

Query: object

Parsed query string.

🤝 Contributing

It's a very simple project. Any contribution, any feedback is greatly appreciated.

⭐ Support

If this project was useful to you, consider giving it a star on github, it's a way to increase evidence and attract more contributors.

🙏 Acknowledgment

This work is hugely influenced by these amazing projects:

A huge thank you to all the people who contributed to these projects.