Skip to content

Commit

Permalink
0.2.6: update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
Tao-VanJS committed May 10, 2023
1 parent 5668722 commit 26f4991
Show file tree
Hide file tree
Showing 9 changed files with 375 additions and 17 deletions.
32 changes: 17 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
**Mini-Van**: A Slimmed-down Version of **VanJS** for Client-side/Server-side DOM Generation
# **Mini-Van**: A Minimalist Template Engine for DOM Generation. Working for both Client-side and Server-side Rendering

**Mini-Van** is the slimmed-down version of [**VanJS**](https://vanjs.org) by stripping out the state and state binding functionalities. **Mini-Van** provides the functionalities of DOM composition and manipulation. Compared to **VanJS**, **Mini-Van** further reduces the bundle size to 0.5kB and can be used on the server-side as a [template engine](https://en.wikipedia.org/wiki/Web_template_system).

**Mini-Van** is part of larger [**VanJS**](https://vanjs.org) project, which aims to provide an ***ultra-lightweight***, ***zero-dependency***, and ***unopinionated*** Reactive UI framework based on pure vanilla JavaScript and DOM.

The `Hello World` program shown in **VanJS** [Home](https://vanjs.org) page also works with **Mini-Van**:
**Mini-Van** is an ***ultra-lightweight*** template engine for DOM composition and manipulation. With only 0.5kB in the minized bundle size, **Mini-Van** enables you to build comprehensive UI with elegant and expressive vanilla JavaScript code:

```javascript
// Reusable components can be just pure vanilla JavaScript functions.
Expand All @@ -22,25 +18,31 @@ van.add(document.body, Hello())
// document.body.appendChild(Hello())
```

[Try on jsfiddle](https://jsfiddle.net/gh/get/library/pure/vanjs-org/vanjs-org.github.io/tree/master/jsfiddle/minivan/hello)

You can convert any HTML snippet into **Mini-Van** code with our online [converter](https://vanjs.org/convert).

**Mini-Van** is the slimmed-down version of [**VanJS**](https://vanjs.org), which aims to provide an ***ultra-lightweight***, ***zero-dependency***, and ***unopinionated*** Reactive UI framework based on pure vanilla JavaScript and DOM. Compared to **VanJS**, **Mini-Van** further reduces the bundle size to 0.5kB and can be used on the server-side as a [template engine](https://en.wikipedia.org/wiki/Web_template_system).

## Getting Started on the Client-Side

To get started with **Mini-Van**, download the latest version [`mini-van-0.2.5.min.js`](https://vanjs.org/autodownload?file=mini-van-0.2.5.min.js) and add the line below to your script:
To get started with **Mini-Van**, download the latest version [`mini-van-0.2.6.min.js`](https://vanjs.org/autodownload?file=mini-van-0.2.6.min.js) and add the line below to your script:

```javascript
import van from "./mini-van-0.2.5.min.js"
import van from "./mini-van-0.2.6.min.js"
```

To code without ES6 modules, you can download the bundled version [`mini-van-0.2.5.nomodule.min.js`](https://vanjs.org/autodownload?file=mini-van-0.2.5.nomodule.min.js) and add the following line to your HTML file instead:
To code without ES6 modules, you can download the bundled version [`mini-van-0.2.6.nomodule.min.js`](https://vanjs.org/autodownload?file=mini-van-0.2.6.nomodule.min.js) and add the following line to your HTML file instead:

```html
<script type="text/javascript" src="mini-van-0.2.5.nomodule.min.js"></script>
<script type="text/javascript" src="mini-van-0.2.6.nomodule.min.js"></script>
```

You can find all relevant **Mini-Van** files in this [Download Table](https://vanjs.org/minivan#download-table).

## API Reference

**Mini-Van** exposes the same set of APIs as **VanJS** for DOM composition and manipulation. Thus for API reference, you can refer to [DOM Composition and Manipulation](https://vanjs.org/tutorial#dom) section of **VanJS** tutorial. Note that: state and state binding is not supported in **Mini-Van**.
**Mini-Van** exposes the same set of APIs as **VanJS** for DOM composition and manipulation. Thus for API reference, you can refer to [DOM Composition and Manipulation](https://vanjs.org/tutorial#dom) section of **VanJS** tutorial. Note that: state and state binding are not supported in **Mini-Van**.

## Server-Side: Deno Integration

Expand All @@ -54,7 +56,7 @@ In `van-plate` mode, HTML content is generated purely through text templating. I

```typescript
import { serve } from "https://deno.land/std@0.184.0/http/server.ts"
import van from "https://deno.land/x/minivan@0.2.5/src/van-plate.js"
import van from "https://deno.land/x/minivan@0.2.6/src/van-plate.js"

const {a, body, li, p, ul} = van.tags

Expand Down Expand Up @@ -83,7 +85,7 @@ await serve(req => new Response(
), {port})
```

As illustrated in the example, `render` method can be called on the object returned from the [tag function](https://vanjs.org/tutorial#api-tags) to generate a `string` that can be used for serving.
As illustrated in the example, `render` method can be called on the object returned from the [`tag function`](https://vanjs.org/tutorial#api-tags) to generate a `string` that can be used for serving.

`van.html` is a helper function defined in `van-plate.js` that is equivalent to:

Expand All @@ -93,14 +95,14 @@ As illustrated in the example, `render` method can be called on the object retur

### `mini-van` mode

The behavior in `mini-van` mode is similar to the behavior in browser context. i.e.: DOM objects will be created by [tag functions](https://vanjs.org/tutorial#api-tags). As Deno doesn't have the built-in support for DOM objects, you need to provide a 3rd-party `Document` object before integrating with **Mini-Van** in this mode.
The behavior in `mini-van` mode is similar to the behavior in browser context. i.e.: DOM objects will be created by [`tag functions`](https://vanjs.org/tutorial#api-tags). As Deno doesn't have the built-in support for DOM objects, you need to provide a 3rd-party `Document` object before integrating with **Mini-Van** in this mode.

There are multiple 3rd-party options for the `Document` object. In the example below, we will demonstrate the integration with the help of [deno-dom](https://deno.com/manual@v1.28.1/advanced/jsx_dom/deno_dom):

```typescript
import { serve } from "https://deno.land/std@0.184.0/http/server.ts"
import { DOMParser } from "https://deno.land/x/deno_dom@v0.1.38/deno-dom-wasm.ts"
import van from "https://deno.land/x/minivan@0.2.5/src/mini-van.js"
import van from "https://deno.land/x/minivan@0.2.6/src/mini-van.js"

const document = new DOMParser().parseFromString("", "text/html")!
const {tags, html} = van.vanWithDoc(document)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mini-van",
"version": "0.2.5",
"version": "0.2.6",
"description": "A slim version of VanJS with only DOM composition and manipulation.",
"main": "src/mini-van.js",
"type": "module",
Expand Down
152 changes: 152 additions & 0 deletions public/mini-van-0.2.6.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
export type Primitive = string | number | boolean | bigint

export type PropValue = Primitive | Function | null

export interface Props {
readonly [key: string]: PropValue
}

export type ChildDom<ElementType, TextNodeType> = Primitive | ElementType | TextNodeType
| readonly ChildDom<ElementType, TextNodeType>[]

type AddFunc<ElementType, TextNodeType> =
(dom: ElementType, ...children: readonly ChildDom<ElementType, TextNodeType>[]) => ElementType

export type TagFunc<ElementType = Element, TextNodeType = Text, ResultType = ElementType> =
(first?: Props | ChildDom<ElementType, TextNodeType>,
...rest: readonly ChildDom<ElementType, TextNodeType>[]) => ResultType

type Tags<ElementType, TextNodeType> = {
readonly [key: string]: TagFunc<ElementType, TextNodeType>
}

// Tags type in browser context, which contains the signatures to tag functions that return
// specialized DOM elements.
type BrowserTags = Tags<Element, Text> & {
// Register known element types
// Source: https://developer.mozilla.org/en-US/docs/Web/HTML/Element

// Main root
readonly html: TagFunc<Element, Text, HTMLHtmlElement>

// Document metadata
readonly base: TagFunc<Element, Text, HTMLBaseElement>
readonly head: TagFunc<Element, Text, HTMLHeadElement>
readonly link: TagFunc<Element, Text, HTMLLinkElement>
readonly meta: TagFunc<Element, Text, HTMLMetaElement>
readonly style: TagFunc<Element, Text, HTMLStyleElement>
readonly title: TagFunc<Element, Text, HTMLTitleElement>

// Sectioning root
readonly body: TagFunc<Element, Text, HTMLBodyElement>

// Content sectioning
readonly h1: TagFunc<Element, Text, HTMLHeadingElement>
readonly h2: TagFunc<Element, Text, HTMLHeadingElement>
readonly h3: TagFunc<Element, Text, HTMLHeadingElement>
readonly h4: TagFunc<Element, Text, HTMLHeadingElement>
readonly h5: TagFunc<Element, Text, HTMLHeadingElement>
readonly h6: TagFunc<Element, Text, HTMLHeadingElement>

// Text content
readonly blockquote: TagFunc<Element, Text, HTMLQuoteElement>
readonly div: TagFunc<Element, Text, HTMLDivElement>
readonly dl: TagFunc<Element, Text, HTMLDListElement>
readonly hr: TagFunc<Element, Text, HTMLHRElement>
readonly li: TagFunc<Element, Text, HTMLLIElement>
readonly menu: TagFunc<Element, Text, HTMLMenuElement>
readonly ol: TagFunc<Element, Text, HTMLOListElement>
readonly p: TagFunc<Element, Text, HTMLParagraphElement>
readonly pre: TagFunc<Element, Text, HTMLPreElement>
readonly ul: TagFunc<Element, Text, HTMLUListElement>

// Inline text semantics
readonly a: TagFunc<Element, Text, HTMLAnchorElement>
readonly br: TagFunc<Element, Text, HTMLBRElement>
readonly data: TagFunc<Element, Text, HTMLDataElement>
readonly q: TagFunc<Element, Text, HTMLQuoteElement>
readonly span: TagFunc<Element, Text, HTMLSpanElement>
readonly time: TagFunc<Element, Text, HTMLTimeElement>

// Image and multimedia
readonly area: TagFunc<Element, Text, HTMLAreaElement>
readonly audio: TagFunc<Element, Text, HTMLAudioElement>
readonly img: TagFunc<Element, Text, HTMLImageElement>
readonly map: TagFunc<Element, Text, HTMLMapElement>
readonly track: TagFunc<Element, Text, HTMLTrackElement>
readonly video: TagFunc<Element, Text, HTMLVideoElement>

// Embedded content
readonly embed: TagFunc<Element, Text, HTMLEmbedElement>
readonly iframe: TagFunc<Element, Text, HTMLIFrameElement>
readonly object: TagFunc<Element, Text, HTMLObjectElement>
readonly picture: TagFunc<Element, Text, HTMLPictureElement>
readonly source: TagFunc<Element, Text, HTMLSourceElement>

// Scripting
readonly canvas: TagFunc<Element, Text, HTMLCanvasElement>
readonly script: TagFunc<Element, Text, HTMLScriptElement>

// Demarcating edits
readonly del: TagFunc<Element, Text, HTMLModElement>
readonly ins: TagFunc<Element, Text, HTMLModElement>

// Table content
readonly caption: TagFunc<Element, Text, HTMLTableCaptionElement>
readonly col: TagFunc<Element, Text, HTMLTableColElement>
readonly colgroup: TagFunc<Element, Text, HTMLTableColElement>
readonly table: TagFunc<Element, Text, HTMLTableElement>
readonly tbody: TagFunc<Element, Text, HTMLTableSectionElement>
readonly td: TagFunc<Element, Text, HTMLTableCellElement>
readonly tfoot: TagFunc<Element, Text, HTMLTableSectionElement>
readonly th: TagFunc<Element, Text, HTMLTableCellElement>
readonly thead: TagFunc<Element, Text, HTMLTableSectionElement>
readonly tr: TagFunc<Element, Text, HTMLTableRowElement>

// Forms
readonly button: TagFunc<Element, Text, HTMLButtonElement>
readonly datalist: TagFunc<Element, Text, HTMLDataListElement>
readonly fieldset: TagFunc<Element, Text, HTMLFieldSetElement>
readonly form: TagFunc<Element, Text, HTMLFormElement>
readonly input: TagFunc<Element, Text, HTMLInputElement>
readonly label: TagFunc<Element, Text, HTMLLabelElement>
readonly legend: TagFunc<Element, Text, HTMLLegendElement>
readonly meter: TagFunc<Element, Text, HTMLMeterElement>
readonly optgroup: TagFunc<Element, Text, HTMLOptGroupElement>
readonly option: TagFunc<Element, Text, HTMLOptionElement>
readonly output: TagFunc<Element, Text, HTMLOutputElement>
readonly progress: TagFunc<Element, Text, HTMLProgressElement>
readonly select: TagFunc<Element, Text, HTMLSelectElement>
readonly textarea: TagFunc<Element, Text, HTMLTextAreaElement>

// Interactive elements
readonly details: TagFunc<Element, Text, HTMLDetailsElement>
readonly dialog: TagFunc<Element, Text, HTMLDialogElement>

// Web Components
readonly slot: TagFunc<Element, Text, HTMLSlotElement>
readonly template: TagFunc<Element, Text, HTMLTemplateElement>
}

type VanWithDoc = <ElementType, TextNodeType>(
doc: {
createElement(s: any): ElementType,
createTextNode(s: any): TextNodeType,
}) => {
add: AddFunc<ElementType, TextNodeType>
tags: Tags<ElementType, TextNodeType>
html: (first?: Props | ChildDom<ElementType, TextNodeType>,
...rest: readonly ChildDom<ElementType, TextNodeType>[]) => string
}

export type Van = {
readonly vanWithDoc: VanWithDoc
readonly add: AddFunc<Element, Text>
readonly tags: BrowserTags
html: (first?: Props | ChildDom<Element, Text>,
...rest: readonly ChildDom<Element, Text>[]) => string
}

declare const van: Van

export default van
28 changes: 28 additions & 0 deletions public/mini-van-0.2.6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/// <reference types="./mini-van.d.ts" />

// This file consistently uses `let` keyword instead of `const` for reducing the bundle size.

// Aliasing some builtin symbols to reduce the bundle size.
let Obj = Object

let vanWithDoc = doc => {
let toDom = v => v.nodeType ? v : doc.createTextNode(v)

let _result = {
add: (dom, ...children) => (
children.flat(Infinity).forEach(child => dom.appendChild(toDom(child))), dom),

tags: new Proxy((name, ...args) => {
let [props, ...children] = args[0]?.constructor === Obj ? args : [{}, ...args]
let dom = doc.createElement(name)
Obj.entries(props).forEach(([k, v]) =>
dom[k] !== undefined ? dom[k] = v : dom.setAttribute(k, v))
return _result.add(dom, ...children)
}, {get: (tag, name) => tag.bind(null, name)}),

"html": (...args) => "<!DOCTYPE html>" + _result.tags.html(...args).outerHTML,
}
return _result
}

export default {"vanWithDoc": vanWithDoc, ...vanWithDoc(window.document)}
Loading

0 comments on commit 26f4991

Please sign in to comment.