4.7.2 • Published 1 year ago

neobiz v4.7.2

Weekly downloads
-
License
MIT
Repository
-
Last release
1 year ago

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,
};
propertiescallerreturn-typedescription
_renderObjectstringrendering to HTML
outFileObject @params destinationstringvoidgenerate static HTML file
rangeArray @params lengthint, startintArrayshortcut for looping in a range
repulseStringObjectgenerate object from HTML string
cssObjectObjectgenerate css from object
cssTextObjectObjectinline css
alter trialsObject @params cbfunctionObjectaltering object before rendering
regObjectvoidregistring an object
regmObjectvoidupdating the existing registered object
loadObjectObjectread an existing registered object
unredObjectvoidremoving an existing registered object
renderOptionObject @params optionObjectvoidset 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.

4.7.2

1 year ago

4.7.0

1 year ago

4.5.0

1 year ago

4.3.12

1 year ago

4.3.11

1 year ago

4.1.15

1 year ago

4.1.14

1 year ago

3.8.1

1 year ago

3.3.0

1 year ago

3.1.0

1 year ago

1.4.0

1 year ago

1.3.9

1 year ago

1.3.6

1 year ago

1.3.5

1 year ago

1.3.4

1 year ago

1.3.1

1 year ago

1.2.5

1 year ago

1.2.4

1 year ago

1.2.2

1 year ago

1.2.1

1 year ago

1.2.0

1 year ago

1.0.0

1 year ago