Skip to content

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

License

Notifications You must be signed in to change notification settings

marcodpt/merlin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

65 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

  • No building tools.
  • Single HTML file by default.
  • Built by combining ideas from small modules following the UNIX philosophy.
  • Pure functional ELM architecture state management library.
  • Ultrafast vDom.
  • Server side rendered by default (templates are valid html).
  • Built-in Single Page Application Router.
  • Ridiculously small API. After reading this file you will understand Merlin better than me.

💡 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

  • Counter: Demo Source
  • Todo SSR: Demo Source
  • Clock: Demo Source
  • Stopwatch: Demo Source
  • Table: Demo Source
  • Components: Demo Source
  • SPA Router: Demo HTML JS

📖 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.