neobiz

4.7.2 • Public • Published

Documentation Neobiz.js 4.7.x

A simple view engine that has 100% JS features

Neobiz.js is pure in JS lang, transform Object into HTML

fix error outFIle

Updates:

  • fix event bugs
  • Boolean attributes / non-value attribute (example: disabled, readonly)

prev update:

  • render method change to **\_render**to avoid conflict with another library and add safety check
  • render option props improve
  • fix bug on child order

features:

  • eventHandler
  • Reusable & editable style/css
  • Altering object
  • Registering component
  • Explicit tag name supported

read /example dir to better understanding

for browser usage use browser.js file.

link to usage in express.js


Example with vue in browser

page.js

import "neobiz";

({
  div: {
    script: [
      { src: "https://unpkg.com/vue@3/dist/vue.global.js" },
      { src: "https://unpkg.com/neobiz@3.1.0/browser.js" },
      { src: "./my-component.js" },
    ],
    id: "app",
  },
  script: {
    html() {
      const { createApp } = Vue;

      createApp(myComponent).mount("#app");
    },
  },
}.outFile("./welcome.html"));

my-component.js

const myComponent = {
  data() {
    return { msg: "hi, this is example" };
  },
  template: { h1: { text: "{{msg}}" } }._render,
};

properties caller return-type description
_render Object string rendering to HTML
outFile Object @params destination[string] void generate static HTML file
range Array @params length[int], start[int] Array shortcut for looping in a range
repulse String Object generate object from HTML string
css Object Object generate css from object
cssText Object Object inline css
alter [trials] Object @params cb[function] Object altering object before rendering
reg Object void registring an object
regm Object void updating the existing registered object
load Object Object read an existing registered object
unred Object void removing an existing registered object
renderOption Object @params option[Object] void set the option for rendering

Why use this?

  • Easy maintance innerHTML rather than literal string
  • Generate static html file
  • Full control of view. Such as filtering, encrypting the data before serve, or just like conditional and loop case
  • Almost no need to learn anything. Just need to learn how to render
  • Limitless potential, because it's just js. Almost all library should be compatible

Basic syntax

How to use? just import this:

import "neobiz";

It's just an Object! wrap in () to create a statement or just assign to a var

{
  // text property is same as innerText
  h1: {
    text: "Hello World!",
  },
}._render;
// <h1>Hello World!</h1>

or use call method

_render.call({
  // text property is same as innerText
  h1: {
    text: "Hello World!",
  },
});

Comments:

{
  // this is comment
  /*
  this is multi line
  */
  h1: {
    text: "This is heading";
  }
}

properties dom

{
  h1: {
    class:"heading",
    text: "Hello World!",
    style:"color: #DC1E1E",
  }
}
// <h1 class="heading" style="color: #DC1E1E">Hello World!</h1>

boolean attributes

use Null to indicate non-value attributes, do not confuse Null to null

{
    button: { text: "Hello World!", disabled: Null },
  }._render

innerText & innerHTML:

  {
    h1: { text: "<b>this is a text</b>" },
    ul: { html: "<li>this will be render as html</li>" },
  }

nested dom:

{
  body: {
    h1: {
      text: "Hello World!",
    }
  }
}

expression & operator

{
  span: [
    { text: 24 + 12 / 6 },
    { text: !false },
  ],
}

siblings dom:

There is a case like this:

<li>orange</li>
<li>banana</li>

Object can not use 2 keys with the same name

// Don't do this
{
  li:{text:"orange"},
  li:{text:"banana"},
}

// Do this
{
  li:[
    {text:"orange"},
    {text:"banana"},
  ]
}

Render Option

renderOption({
  camelCase: false,
  once: false,
  nodoctype: false,
  ignoreTag: false,
  prefixTag: false,
  prefixAttr: false,
});

set once to true to use option only for once,

set nodoctype to true to remove <!doctype html> in the beninging,

set ignoreTag to true to unused tag properties,

set prefixTag to something to add text before tag,
use noprefix:true to skip on specific object

set prefixAttr to something to add text before attribute,
use nopAttr:true to skip in specific object

set camelCase true to convert camelCase properties to kebab-case

make sure to set the option before rendering

renderOption({
  camelCase: true,
});

render.call({
  ionRouter: {},
});

result

<ion-router></ion-router>

Explicit tag name

What if there is somethings in the middle of list?

<li>orange</li>
<p>
  <span>This is in the middle</span>
</p>
<li>banana</li>

if we use an array there will share the tag name right? just use this:

use string as key could distinc an element with just a space no need to worry, it will render without space

{
  li:{text:"orange"},
  p:{span:{text:"This is in the middle"}},
  "li ":{text:"banana"},
}

or write the tag name:

{
  li: [
    { text: "orange" },
    { tag: "p", span: { text: "This is in the middle" } },
    { text: "banana" },
  ],
}

also with specifying tag name, we can name it differently:

  {
    PersonList: ["Arthur", "Zoro"].map((person) => ({
      tag: "li",
      text: person,
    })),
  }

Modify an Object

use alter properties, with function as params. no need to return a value

const y = {
  h1: { text: "Hello World!" },
  p: { text: "this is a p" }.alter((e) => (e.class = "lorem")),
}.alter((e) => {
  e.h1.text = "thi is altered text";
  e.h1.style = { color: "red", fontSize: "150%" }.cssText;
});

console.log(y.render);

Components / Partials

import header from "./header.v.js"; //function type
import footer from "./footer.v.js"; //object type

{
  div: header({ user: "dim24" }),
  p: { text: "this is text" },
  div: footer,
}.render;

header.v.js

export default ({ user }) => ({ h1: { text: `Hi, ${user}` } });

footer.v.js

export default {
  script: { src: "/assets/js/main.js" },
  span: { text: "this is footer" },
};

reg, regm, load & unreg Components

The idea is to make object has resuability

reg & load

this function need a single argument to set a name of registering object,

there is 2 ways to registering an component:

  • through properties method:
{ name:"viewport"}.reg("viewport")
  • via call method:
reg.call({ name: "viewport" }, "viewport");

now we can load it's value whenever we want

{
  meta:load("viewport"),
  body: {
  }
}

regm

this function will replace an existing registered object with a new value:

const newValue = load("viewport");
newValue.content = "width=device-width, initial-scale=1.0";

newValue.regm("viewport");

unreg

when we the object doesn't needed anymore, just unreg it:

unreg("viewport");

Style

use camel case to css properties

inline CSS:

{
  h1:{
    text:"Hello World",
    style:{
      color:"#1B73F8",
      fontSize:"150%"
    }.cssText
  }
}

use style :

global-style.js:

export default {
  h1: {
    color: "red",
  },
  body: {
    margin: "0px",
    textAlign: "center",
  },
};

why should use object css rather than direct css?

we can easily modify the style

main-page.js:

import style from "./global-style.js";

style.body.margin = "12px";

{
  style:style.css,
  div:{
    h1:{text:"Hello World!"}
  }
}.render

reusable style / mixin

const flex = (justify, align, direction = "row") => ({
  display: "flex",
  justifyContent: justify,
  alignItems: align,
  flexDirection: direction,
});

const space = {
  padding: "6px 8px",
  margin: "6px 10px",
};

console.log({
  style: { div: flex("center", "center"), button: { border: "none", ...space } }
    .css,
});

Interacting with DOM

use script to interact with browser with html property

wrap the script with a function, or use string

{
  button:{onclick:"sayHi(this)",id:"hi-button"},
  script:{
    html(){
      document.getElementById("hi-button").innerText="Click me!";

      function sayHi(el){
        el.innerText="Hi!";
      }
    }
  }
}

Event

you can add an event this keyword always refered to the node itseft

{
  input:{type:"password",onkeypress(){
    if(event.keyCode==13)
    alert(this.value)
  }},
  button:{text:"Click me!",onclick(){
    this.innerText = this.innerText=="clicked"?"Click me!":"clicked";
  }}
}

Repulse

If you already have an html file and want to modify it, or make it as a template, just use this

this function is still has a lot issues, use only in a simple case

  • need to wrap all tag into a single parent
  • recommended to use external script and css
  • repetitive / nested could caused weird behavior (help me, please!)

I still try to improve this feature. if you can provide some help just tell me please... :)

const { div } = `
<div>
    <h1>Hello dims!</h1>
</div>
`.repulse;

div.id = "main";
div.h1.class = "heading";
div.p = { text: "this is a whole text" };

console.log({ div }.render);

result

<div id="main">
  <h1 class="heading">Hello dims!</h1>
  <p>this is a whole text</p>
</div>

Pass Value

use shorthand anonym function

console.log(((user) => ({ h1: { text: `Hello, ${user}` } }))("Vins").render);

or

const greeting = (user) => ({ h1: `Hello, ${user}` });

console.log(greeting("Vins").render);

Control Flow

ternary:

{
    h1: status
      ? { text: "Hello World!" }
      : {
          a: { href: "#", text: "You are offline!" },
        },
}

IIFE if-else

{
    h1: (() => {
      let result;
      if (status) result = { text: "Hello World!" };
      else
        result = {
          a: { href: "#", text: "You are offline!" },
        };
      return result;
    })(),
}

normal if else

let result;
if (status) result = { text: "Hello World!" };
else
  result = {
    a: { href: "#", text: "You are offline!" },
  };

//use
{
  h1: result,
}

IIFE switch-case

{
    h1: (() => {
      let result;
      switch (status) {
        case true:
          result = { text: "Hello World!" };
          break;
        case false:
          result = {
            a: { href: "#", text: "You are offline!" },
          };
      }
      return result;
    })(),
}

Loop & array manipulation

range & map:

  {
    ul: {
      li: [].range(8, 1).map((item) => ({ text: "data-" + item })),
    },
  }

map

  {
    ul: {
      li: ["grape", "banana", "apple"].map((text) => ({ text })),
    },
  }

filter

{
  ul: {
    li: [].range(8, 1).filter( num => num % 2 == 0 ).map((item) => ({ text: "data-" + item })),
  },
}

for

  {
    ul: {
      li: (() => {
        const result = [];
        for (let i = 1; i < 9; i++) result.push({ text: "data-" + i });
        return result;
      })(),
    },
  }

while

  {
    ul: {
      li: (() => {
        const result = [];
        let i = 0;
        while (++i < 9) result.push({ text: "data-" + i });
        return result;
      })(),
    },
  }

templating

this example use single file usage. for modular usage leave to you, or just read the example dir

//template file
const template = (content) => ({
  div: {
    class: "main wrapper",
    div: content,
  },
});

//content file
template({
  h1: { text: "Hello World!" },
});

Thank you for read until here.

Package Sidebar

Install

npm i neobiz

Weekly Downloads

4

Version

4.7.2

License

MIT

Unpacked Size

31.7 kB

Total Files

23

Last publish

Collaborators

  • dim24