GithubHelp home page GithubHelp logo

atmajs / maskjs Goto Github PK

View Code? Open in Web Editor NEW
92.0 10.0 6.0 23.06 MB

Markup | Template | HMVC

Home Page: http://atmajs.com/mask

License: MIT License

JavaScript 7.11% HTML 0.54% Mask 0.56% CSS 0.01% TypeScript 91.79%
templating-language components modules hmvc

maskjs's Introduction


MaskJS β€” is a markup | template | modular HMVC engine for modern and fast web(Browser), server(NodeJS) or mobile(PhoneGap) applications. Component-based architecture simplifies defining, implementing and composing loosely coupled independent elements into a single application.

Resources:


☰

1 Markup

We support mask and html syntax for writing your templates. And you can even mix them within one template, as each of them has its advantages.

1.1 Mask Syntax
  • Component and element-based markup
  • Statements, Expressions, Interpolations
  • Performance. No precompilation is required
  • Small size. ~30% smaller than HTML Additionaly, there is a minification tool - Optimizer.
  • DOM Builder [Template β†’ Mask AST β†’ Shadow DOM β†’ Live DOM]
  • HTML Builder (nodejs) [Template β†’ Mask AST β†’ HTML]
import CustomComponent from 'Foo.mask'

.container {
    h4 > 'Title'
    section.content {
        span > 'Hello ~name!'

        if (admins.includes(name)) {
            em > 'Admin'
        }
    }
    CustomComponent {
        button x-tap='changeName' >
            '~[bind: name]'

        for (tag of tags) {
            h4 > '~tag.title'
        }
    }
}
1.2 HTML Syntax

Here is nothing new for you. Old good HTML syntax to define the templates. But we highly encourage to use the mask syntax, as the templates are smaller, cleaner and with additional features.

<h4>~[name]</h4>
<Dialog>
    <div>Hello Foo</div>
</Dialog>
1.3 HTML within Mask

You can even use html blocks in a mask syntax

ul {
    <li> Foo
    <li> Bar
}

MaskJS has extremely extendable API based on interfaces and contracts. It supports Custom Tag Handlers, Custom Attribute Handlers, Model Utils.

MaskJS default build contains sub projects: CompoJS, Bindings, jMask.

2 Libaries

πŸ“¦ All packages are already embedded into MaskJS sources.

2.1 Components

πŸ“™ Read more...↡

Core of the HMVC engine. Simple compo sample:

export class CustomComponentCtr {

    // slots example
    @mask.deco.slot()
    onRefreshDate (){
        this.model.date = new Date();
    }
    @mask.deco.slot()
    domInsert (){
        alert(this.$.innerWidth());
    }

    // events example
    @mask.deco.event('click: button')
    onButtonClicked (){
        alert(this.model.date);
    }

    onRenderStart (model, ctx) {
        // override model
        this.model = { date: new Date(); }
    }
    onRenderEnd: function(elements, model, ctx){
        this.$ // is a domLibrary (jQuery-lite, jQuery/Zepto/Kimbo) wrapper over `elements`
    }

    dispose () {
        // do some cleanup
    }
};
import './CustomComponent.less'
import CustomComponentCtr from './CustomComponentCtr.ts'

define CustomComponent extends CustomComponentCtr {
    h1 {
        'Date ~[bind: _.formatDate(date)]'
    }
    button .btn x-tap='onRefreshDate' {
        i.material-icons > 'update'
        'Refresh'
    }
}

2.2 Bindings

πŸ“™ Read more...↡ IE9+

MaskJS itself supports simple interpolations. It means the models are only accessed while render, but with this feature you can define single or dual bindings. As MaskJS is a DOM based engine, the bindings are instant.

Simple bindings sample:

h4 > '~[bind: fooDate.getSeconds() * barAge ]'

input type=date >
    dualbind value='fooDate';

input type=number >
    dualbind value='barAge';
/*\
 * `dualbind` component also supports much more properties and configurations
\*/

2.3 jMask

πŸ“™ Read more...↡

jMask offers jQuery-alike syntax for the dynamic MaskDOM Manipulations.

2.4 jQuery

MaskJS is loosely coupled with the DOM Library, like jQuery-Zepto-Kimbo. It means, that it does not depend on any DOM library, but it is highly recommended to use one. Additionally there are some extensions, like

$.fn.appendMask
$.fn.prependMask
$.fn.beforeMask
$.fn.afterMask
$.fn.emptyAndDispose
$.fn.removeAndDispose
//e.g.
$('.foo').appendMask('h4 > "~[title]"', { title: 'Hello' });

So you would never need to use the HTML.

2.5 Dependency Injection

πŸ“™ Read more...↡

You can annotate arguments for define declaration or for its constructor and if you don't provide the values on initialization MaskJS will do it for you using registered IoC container.

The library is not include, you can use any other DI library. MaskJS only requires an IoC container with a single method: .resolve(Type):Any.

import * as IStore from services;

define UserList (store: IStore) {

    foreach (user of store.getUsers()) {
        div > '~user.username'
    }

    // or in constructor
    function constructor (store: IStore) {
        this.store = store;
    }
}

3 Performance

We thoroughly pay attention to the performance, especially on the mobile CPU. The DOM based and the Shadow DOM approach is the fastest way to create hierarchical component structure.

Some benchmarks:

4 Node.JS

MaskJS on the server

πŸ“™ Mask.Node ↡ Server.Lib ↡

  • HMVC benefits
  • Models serialization/de-serialization
  • Components render mode - server, client or both
  • HTML rendered output with further bootstrapping on the client, so that the components are initialized, all events and bindings are attached
  • Application start performance: browser receives ready html for rendering.
  • SEO

5 Browser Support

  • IE7+

6 Plugins

There are already many plugins, components and useful utilities. Some of them worth to checking out:

7 Quick Start

Most simple MaskJS sample to show where you could start from:

<!DOCTYPE html>
<html>
    <body>
        <script type='text/mask' data-run='auto'>
            import Counter from './Counter';

            h4 > 'Counter with 1 second step'
            Counter x-interval=1;

            h4 > 'Counter with 5 seconds step'
            Counter x-interval=5;
        </script>
        <script src='https://unpkg.com/maskjs'></script>
    </body>
</html>
// Create the file `Counter.mask`
define Counter {
    var meta = {
        attributes: {
            'x-interval': 'number'
        }
    };

    var scope = {
        counter: 0,
        timer: null
    };

    slot domInsert () {
        this.scope.timer = setTimeout(() => {
            ++this.scope.counter;
        }, this.xInterval)
    }

    function dispose () {
        clearTimeout(this.scope.timer);
    }

    div > '~[bind: this.scope.counter]
}

8 Contribute

8.1 Build

$ git submodule init && git submodule update
$ npm install
$ npm run build

8.2 Test

$ npm install
$ npm test

9 Changelog


πŸ”– View complete list...↡ @latest

  • 0.64.0

  • Properties

    div [style.backgroundColor] = 'red';

@latest

  • 0.60.0

  • Await statements, components and also modules

    define Foo {
        function async onRenderStart () {
            this.model = await LoadUserExample();
        }
        h4 > '~userName'
    }
    
    // Component
    await Foo {
        @progress > i > 'Loading user';
    }
    
    // Promises
    await (this.getCurrentUser()) {
        @progress > i > 'Loading user';
        @done (user) {
            h4 > '~user.userName'
        }
        @fail (error) {
            .danger > '~error.message'
        }
    }
    
    // Modules
    import async Foo from './Foo';
    
    heading > 'Some heading'
    await Foo {
        @progress > 'Loading and initilizing the module'
    }
  • 0.58.0

  • Decorators for methods and nodes

    [IsAuthorized]
    div > 'Hello ~user'
    
    [LogCall]
    function doSmth () {
        // ...
    }
  • Async and Private methods. For browsers which do not yet support async/await es2017 feature, please use postmask-babel plugin.

    slot private async upload () {
        await MyService.doSmth();
    }
  • 0.57.13

  • Modules

    • Namespace routing

      import FooService from services;
      
      h4 > '~FooService.doSmth()'

      You can also configurate the base path for the routing, e.g. mask.Module.cfg('baseNs', '/src/')

      If the module is not loaded or not set to the namespace repository, we will load it for you by the resolved path, e.g. '/src/services/FooService.js'

    • Prefix routing

      import MyButton from '@controls/MyButton';
      MyButton x-tap='clicked';

      You have to configurate the prefix first, e.g.:

      mask.Module.cfg('prefixes.controls', '/src/controls/{0}/{1}.mask');
  • 0.57.0

  • Typa annotations for arguments: (argumentName: argumentType, ...)

    import * as IFoo from '/service/IFoo.js';
    import * as IBar from '/service/IBar.js';
    define MyCompo (foo: IFoo) {
        function constructor (bar: IBar) {
            this.bar = bar;
        }
        span > `~[foo.someMethod()]`
    }
  • 0.56.5

  • Function scope: imports and define arguments

    import * as Service from '/services/UserService.js';
    define UserEditor (user) {
    
        slot save () {
            Service
                .changeUserName(user.id, user.name)
                .then(() => console.log('saved!'));
        }
    
        input > dualbind value='user.name';
        button x-tap=save > 'Save'
    }
  • sync imports, as import loading for better performance is parallel, but bundles should be loaded in sync, as they register all resources then.

import sync from './MyComponentsBundle';
import FooCompo from './Foo';
// ...
  • 0.55.1

    • HTML markup within Mask templates
  • 0.55.0

    • Async imports.

      import async Foo from './Foo.mask';
      h4 > 'MyHeader'
      await Foo;

      h4 header is rendered during the Foo may still being loaded.

    • define and let support arguments

      define Foo (user) {
          h4 > '~user.name'
      }
      
      Foo(me);
      mask.render(template, { me: { name: 'TestUser' }});

©️ MIT - 2021 Atma.js Project

maskjs's People

Contributors

re1ro avatar tenbits avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

maskjs's Issues

mask.Js - Unused variables

// line 500 Unused variable- var c
isCondition = function (con, values) {
if (typeof con === 'string') {
con = parseLinearCondition(con);
}
var current = false,
a, c, value1, value2,
i, length;

// line 826 Unused variable - var singleTags

// line 262 Undeclared variable - mask (Π½ΠΎ Ρ‚ΡƒΡ‚ Π½Π° Ρ‚ΠΎΠ½Π΅Π½ΡŒΠΊΠΎΠ³ΠΎ) :)
mask.compile(template)

Condition removes whitespace

When using the example snippet #{:current > 10 ? "More Than 10":"" } all whitespace is removed from the output resulting in the output of MoreThan10. It appears the culprit is in parseLinearCondition when it removes all whitespace.

Unnecessary leaking into window when Node.js-style modules are used in browser

I'm using LMD for combining multiple JavaScript files into single file with following use in browser. It wraps each JS file into a function:

function(require, exports, module) {
// module code
}

According to recent changes, within this function Mask will set itself as a property of exports and as a property of window. It's superfluous. I'd be nice if only exports property would be set and window would be left unchanged.

Import empty file causes exception

import Foo from 'bar';

When Bar.mask is an empty file _nodesToArray throws an exception as nodes is undefined.

Should do not throw an exception, but should rise an error, as Foo is not exported in bar.mask

Documentation updates

There are several errors in the documentation and it would be extremely useful if everything had more thorough documentation.

Raw HTML in template values?

I expect it is possible, but I cannot work out how to not escape strings containing HTML.

If not already possible, would it be possible to have a "raw" value, which just injects the string, as is (HTML, JavaScript, whatever) ?

Thanks!

Bug in sliceToChar - index is calculated incorrectly...

//fixed Bug - index is calculated incorrectly

    sliceToChar: function (c) {

        var template = this.template,
            index = this.index,
            start = this.index,
            isEscaped = false,
            value, nindex;

        while ((nindex = template.indexOf(c, index)) > -1) {
            index = nindex;  //correct
            if (template.charCodeAt(index - 1) !== 92 /*'\\'*/) {
                break;
            }
            isEscaped = true;
            index++;
        }

        var value = template.substring(start, index);
        this.index = index;
        return isEscaped ? value.replace(regexpEscapedChar[c], c) : value;
    }

Node.js-centric UMD header wrongly expects `global` variable in CommonJS module context

I'm using LMD for combining multiple JavaScript files into single file with following use in browser. It wraps each JS file into a function:

function(require, exports, module) {
// module code
}

LMD expects CommonJS module inside this wrapper and guarantees CommonJS module contract. But it doesn't provide global variable. This is perfectly valid (because global is a Node.js artifact), but it confuses algorithm contained in Mask.js's UMD header.

LMD calls wrapper function in context of window (i.e. this === window) and so Mask leaks its API entrypoint to window (missing a possibility to use provided exports/module)

Unknown license

What is a license of Mask?

Can you please:

/*!
 * jQuery JavaScript Library v2.0.3
 * http://jquery.com/
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 *
 * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2013-07-03T13:30Z
 */

It'd be perfect to include a full license text into JS file banner, but just license name is also fine, if license allows it. Note also importance of /*! comment form (such comments could be skipped by minifiers).

BUG!!! - "div { a > '1' a > '2' ' == ' x1 x2 }" //RESULT IS FALSE -> 12 == 1

// !!! --- BUG ---!!!!

    var x1 = function () {
        this.attr = {}
    }
    x1.prototype.render = function (model, container) {
        return container.appendChild(mask.renderDom(" a > '1' ", model));
    };
    mask.registerHandler('x1', x1);

    var x2 = function () {
        this.attr = {}
    }
    x2.prototype.render = function (model, container) {
        return container.appendChild(mask.renderDom(" a > '2' ", model));
    };
    mask.registerHandler('x2', x2);

    var dom = mask.renderDom("div  { a > '1' a > '2' ' == ' x1 x2  }", null);
    $('div').append(dom);

// RESULT IS FALSE -> 12 == 1

// UPS div { a > '1' a > '2' ' == ' x1; x2 } is ok

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.