Client.constructor(options?: ClientOptions)
Client constructor.
#!/usr/bin/env -S deno serve --allow-read --allow-env
// Server-Side Rendering (SSR) with Mizu
import Mizu from "@mizu/render/server"
export default {
async fetch() {
const headers = new Headers({ "Content-Type": "text/html; charset=utf-8" })
const body = await Mizu.render(`<div *text="foo"></div>`, { context: { foo: "🌊 Yaa, mizu!" } })
return new Response(body, { headers })
},
}#!/usr/bin/env -S deno run --allow-read --allow-env --allow-net --allow-write=/tmp/output
// Static Site Generation (SSG) with Mizu
import Mizu from "@mizu/render/server"
await Mizu.generate([
// Copy content from strings
[`<div *text="foo"></div>`, "index.html", { render: { context: { foo: "🌊 Yaa, mizu!" } } }],
// Copy content from callback return
[() => JSON.stringify(Date.now()), "timestamp.json"],
// Copy content from local files
["**/*", "static", { directory: "/fake/path" }],
// Copy content from URL
[new URL("https://matcha.mizu.sh/matcha.css"), "styles.css"],
], { clean: true, output: "/tmp/output" })
1
2
3
4
5
6
7
8
9
10
111
2
3
4
5
6
7
8
9
10
11
12
13
14
// Server-Side Rendering (SSR) with Mizu
import Mizu from "@mizu/render/server"
import { createServer } from "node:http"
createServer(async (_, response) => {
response.writeHead(200, { "Content-Type": "text/html; charset=utf-8" })
response.end(await Mizu.render(`<div *text="foo"></div>`, { context: { foo: "🌊 Yaa, mizu!" } }))
}).listen(8000, "0.0.0.0", () => console.log("Server is listening"))// Static Site Generation (SSG) with Mizu
import Mizu from "@mizu/render/server"
await Mizu.generate([
// Copy content from strings
[`<div *text="foo"></div>`, "index.html", { render: { context: { foo: "🌊 Yaa, mizu!" } } }],
// Copy content from callback return
[() => JSON.stringify(Date.now()), "timestamp.json"],
// Copy content from local files
["**/*", "static", { directory: "/fake/path" }],
// Copy content from URL
[new URL("https://matcha.mizu.sh/matcha.css"), "styles.css"],
], { clean: true, output: "/tmp/output" })
1
2
3
4
5
6
7
81
2
3
4
5
6
7
8
9
10
11
12
13
// Server-Side Rendering (SSR) with Mizu
import Mizu from "@mizu/render/server"
Bun.serve({
port: 8000,
async fetch() {
const headers = new Headers({ "Content-Type": "text/html; charset=utf-8" })
const body = await Mizu.render(`<div *text="foo"></div>`, { context: { foo: "🌊 Yaa, mizu!" } })
return new Response(body, { headers })
},
})
console.log("Server is listening")// Static Site Generation (SSG) with Mizu
import Mizu from "@mizu/render/server"
await Mizu.generate([
// Copy content from strings
[`<div *text="foo"></div>`, "index.html", { render: { context: { foo: "🌊 Yaa, mizu!" } } }],
// Copy content from callback return
[() => JSON.stringify(Date.now()), "timestamp.json"],
// Copy content from local files
["**/*", "static", { directory: "/fake/path" }],
// Copy content from URL
[new URL("https://matcha.mizu.sh/matcha.css"), "styles.css"],
], { clean: true, output: "/tmp/output" })
1
2
3
4
5
6
7
8
9
10
11
12
131
2
3
4
5
6
7
8
9
10
11
12
13
$
deno add jsr:@mizu/render
npx jsr add @mizu/render
bunx jsr add @mizu/render
<!DOCTYPE html>
<html>
<head>
<title>IIFE</title>
<meta charset="UTF-8" />
</head>
<body>
<main *mizu *set="{ foo: '🌊 Yaa, mizu!' }">
<div *mustache>{{ foo }}</div>
</main>
<!-- Use the IIFE version to automatically start mizu -->
<script src="https://mizu.sh/client.js" defer></script>
</body>
</html><!DOCTYPE html>
<html>
<head>
<title>ESM</title>
<meta charset="UTF-8" />
</head>
<body>
<main *mizu>
<div *mustache>{{ foo }}</div>
</main>
<!-- Use the ESM version to manually control mizu -->
<script type="module">
import Mizu from "https://mizu.sh/client.mjs"
await Mizu.render(document.body, { context: { foo: "🌊 Yaa, mizu!" } })
</script>
</body>
</html>
Switch between browsers and runtimes using the icons above.
Change the current example by clicking on the tabs in the mockups.
Try out our online interactive playground and start experimenting with mizu.js now!
Simply include the library and start building amazing things instantly with vanilla JavaScript expressions and HTML.
Compatible across a wide range of JavaScript and TypeScript runtimes, including all major browsers.
Render your content wherever you need it and however you want it with user-friendly APIs.
Cherry-pick features and craft your own setup easily with developer-friendly APIs and our custom builder.
Build, share and reuse custom elements and directives to supercharge your development.
Want to effortlessly theme your page? Check out matcha.css!Licensed under the MIT License and source code fully available on github.com.
If you enjoy using mizu.js, consider supporting its development.Yes, but hear us out!
Remember when building a web page was as simple as writing some HTML, adding a bit of JavaScript, and styling with CSS? mizu.js brings back that simplicity, offering a modern yet flexible approach to web development.
By adhering closely to web standards and embracing the simplicity of plain HTML and JavaScript, mizu.js offers an almost non-existent learning curve. This makes it an excellent choice for both beginners and seasoned developers.
Whether you're serving content from your favorite runtime, generating static websites, or creating dynamic pages in the browser, mizu.js adapts to your needs. — All of it without the hassle of bundlers, transpilers, or countless dependencies.
We recognize the power and utility of comprehensive frameworks like React, Vue.js, and Angular. These tools excel at building complex applications and boast large communities and ecosystems. However, they can be overwhelming for smaller projects, often requiring a build step and a steep learning curve with their specific syntax and concepts.
Lightweight alternatives such as Alpine.js and htmx are also available. While they perform well in the browser, they were often not designed for server-side use, limiting their applicability across different scenarios.
mizu.js draws inspiration from all these frameworks but is designed from the ground up to be:
If all of this sounds appealing to you, then mizu.js might be the right choice for your next project.
It depends.
On the server-side, mizu.js employs a Virtual DOM to simulate the browser environment. The current implementation leverages JSDOM, but you can use any other Virtual DOM library that adheres to web standards. Non-compliant implementations may lead to unexpected behaviors.
On the client-side, mizu.js interacts directly with the actual DOM. It tracks processed elements and their states using weak references to prevent memory leaks and enhance performance.
We want to ensure mizu.js delivers a reliable and consistent experience across all supported environments, which is why each feature is meticulously documented to detail its behavior and functionality.
Our codebase is thoroughly tested and covered to guarantee that each feature performs as expected. Integration tests are also performed on various platforms and environment to ensure a consistent experience as advertised.
If you encounter any issues or undocumented behavior, please open a new issue so we can address it promptly.
æ°´
is the Japanese kanji for water
.
Like water, mizu.js is fluid and adaptable, seamlessly fitting into various use cases and execution environments.
Like water, mizu.js is simple and fundamental, staying close to vanilla JavaScript and HTML with a minimal learning curve.
Like water, mizu.js is customizable, it can be mixed with other libraries and additional features to suit your needs.
Need to add some flavor to your page? Add some matcha.css to your mizu.js project!*mizu
Enable mizu.js rendering for the element and its children.
[tag] or .modifiers. If it does, the directive will be ignored.
implicit option when using the user API. By default,
rendering is explicit in Client-Side APIs and implicit in Server-Side APIs.
*mizu directive.
*set="context"
Set context values for an element and its children.
Object.
*ref="name"
Create a reference to an element for later use.
*if="expression"
Conditionally render an element.
<template> element, its content is rendered in place of the template which allows to conditionally render several elements at once.
*else="expression"
Conditionally render an element placed after another *if or *else directive.
*if or *else directive.
<template> element, its content is rendered in place of the template which allows to conditionally render several elements at once.
*show="expression"
Conditionally display an element.
display property is set to none !important.
display: none), the element's display property is reset to initial !important.
*if and *else directives, the element remains in the DOM when hidden.
true to hide elements before mizu.js loads (e.g. <style>[\*show]{display:none}</style>).
*for="expression"
Render an element for each iteration performed.
for,
for...in and
for...of loops.
Symbol.iterator.
$key.$value.number.
let,
const and
var declarations inside for loops, but future versions may introduce specific behavior for these.
<template> element, its content is rendered for each iteration instead of the element itself which allows to generate several elements per iteration.
*id directive if present, or the auto-generated identifier.
$i + 1).
$i === 0).
$i === ($iterations - 1)).
*id="expression"
Hint for *for directive to differentiate generated elements.
*for directive.
<template> element, identifiers are only tracked internally and no attribute is set on the generated content.
*empty
Conditionally render an element after a *for directive.
*for or another *empty directive. Elements generated by the *for
directive do not apply to this restriction.
<template> elements, but future versions may introduce specific behavior for these elements.
*for directive. This value may differ from the actual number of iterations processed if conditional directives were applied.
*text="content"
Set element's textContent.
innerHTML
(e.g., <a *text><b></b></a> becomes <a *text><b></b></a>).
*html="content"
Set element's innerHTML.
*mustache
Enable content interpolation within mustaches
({{ and }}) from Text child nodes.
Text nodes, not the entire element.
{{ and }}) and triple mustaches ({{{ and }}}), but future versions may introduce specific behavior for these.
*code="content"
Set element's innerHTML after performing syntax highlighting.
plaintext.
*markdown="content"
Set element's innerHTML after performing markdown rendering.
*markdown[emojis,highlighting,sanitize]). See the full list of supported plugins at @libs/markdown/plugins.
Unsupported plugins will be silently ignored.
<p> tag.
*toc="selector"
Create a table of contents from <h1>...<h6> elements found in selected target.
parentElement. If the parent is an <hgroup> or has a *toc attribute, the search moves to the grandparent element.
*toc).
+ to include higher levels (e.g., *toc).
- to specify multiple levels (e.g., *toc).
ignore to exclude an element from traversal (e.g., *toc). No other modifiers or attribute value should be used with this.
*clean
Clean up the element and its children from specified content.
Comment nodes within the subtree.
) within the subtree.
<template> nodes from the subtree after fully processing it.
.comments modifier is also enabled, comments generated by directives will be removed as well.
*custom-element="tagname"
Register a new custom element.
<template> element.
tagname must be a valid custom element name.
as is.
# elements by <slot> name. The unnamed slot is accessible using $slots[""].
*once.flat directive on the custom element occurences.
#
Specify target <slot> in an element defined by a *custom-element directive.
# directive are appended to the default (unnamed) slot.
*is="tagname"
Set an element tagname.
@="listener"
Listen for a dispatched Event.
@="object"
(e.g., @="{ foo() {}, bar() {} }").
@="{}").@="{}" @="{}").
@="{ FooBar() {}, Foobar() {} }").. in their names, use brackets {}
(e.g. @).
listener only) The dispatched Event.
@click, @click, etc.).
event.preventDefault() when triggered.
event.stopPropagation() when triggered.
{ once: true }.
{ passive: true }.
{ capture: true }.
event.target is the element itself.
window or document).
KeyboardEvent.
plus sign +
(e.g., @keypress).
comma ,
(e.g., @keypress).
alt for "Alt".
ctrl for "Control".
shift for "Shift".
meta for "Meta".
space for " ".
key for any key except "Alt", "Control", "Shift", and "Meta".
event.key.:="value"
Bind an element's attribute value.
:class and :style have specific handling described below.
:="object"
(e.g. :="{ foo: 'bar', bar: true }").
camelCaseconversion if the attribute contains hyphens
-) in the current context. (e.g.,
:data-foo is equivalent to :data-foo="dataFoo").
null or undefined values are removed.
:class="value"
Bind an element's class attribute.
string of space-separated class names (e.g., "foo bar").
Record<PropertyKey, boolean> mapping class names to their state (e.g., { foo: true, bar: false }).
Array of the supported types (e.g., [ "foo", { bar: false }, [] ]).
class attribute value is preserved.
:style="value"
Bind an element's style attribute.
string supported by HTMLElement.style.cssText
(e.g., "color: blue;").
Record<PropertyKey, unknown> mapping CSS properties to their values (e.g., { backgroundColor: "red", "border-color": "green", width: 1 }).
camelCaseinstead of
kebab-caseto avoid escaping CSS property names.
number are implicitly converted to px units when applicable (HTMLElement.style.setProperty() will be called with "px" appended).
Array of the supported types (e.g., [ "color: blue", { backgroundColor: "red" }, [] ]).
style attribute value is preserved.
!important.
::="model"
Bind an <input>, <select> or <textarea> element's value attribute in a bi-directional manner.
<input type="checkbox"> and
<select multiple> elements will bind to an array of values.
@input or @change expressions can cause precedence issues, as the model relies on these events to update. To avoid this, listen to the :: event, which is always triggered after the model has been updated.
value property, such as <input>, <select>, or <textarea>. For other elements, use the : directive.
.nullish, .boolean, .number, and .string modifiers are currently implemented as boolean modifiers, but future versions may change this behavior to offer more parsing features.
::="model" instead of ::="model".
Event that triggers the model update. Recommended events are "input" or "change".
name attribute based on the attribute's value (e.g., <input ::="foo"> becomes <input name="foo">). The
default is true for <input type="radio"> and <input
type="checkbox">, and false for all other elements.
value attribute if present (e.g., <input ::="foo"
value="bar"> assigns foo the value "bar" if it was nullish).
KeyboardEvent. See @event modifier for more information.
null if the value is empty.
Boolean(). Additionally, any non-empty value matching the YAML 1.1 definition of falsy booleanvalues are set to
false.
Number().
String().
%http="url"
Perform a fetch() call that can be handled by %response directives.
%response directive, the request won't be performed automatically. Use %response if you want to trigger the
request but ignore the response.
as is.
%@event directive.
url expression only) The dispatched Event if triggered by a %@event directive, or null.
fetch() should follow redirections.
history.pushState() for the target URL (must be the same origin).
.method[get].
.method[head]
.method[post]
.method[put]
.method[patch]
.method[delete]
%header[]="value"
Set HTTP headers for a %http directive.
undefined or null values are deleted.
Array values are appended together.
%body="content"
Set HTTP body for a %http directive.
Headers object containing all registered headers from %header directives attached to the element.
text: format body with toString().
form: format body with URLSearchParams.
json: format body with JSON.stringify().
xml: format body with stringify() from @libs/xml/stringify.
.type modifier:
text: set Content-Type: text/plain.
form: set Content-Type: application/json.
json: set Content-Type: application/x-www-form-urlencoded.
xml: set Content-Type: application/xml.
.type[text].
.type[form].
.type[json].
.type[xml].
%response="expression"
Reacts to a %http directive's Response.
Response object containing the fetched data.
response.body (type depends on the modifier used).
minus sign - between two numbers (e.g., %response).
comma ,
(e.g., %response).
2XX for 200-299.
3XX for 300-399.
4XX for 400-499.
5XX for 500-599.
response.body:
void: discard body using response.body?.cancel().
text: consume body using response.text() and set element's textContent if no expression
is provided.
html: consume body using response.text(), parse it into a <body> element, and set element's innerHTML if no expression is provided.
json: consume body using response.json().
xml: consume body using response.text() and parse it with parse from @libs/xml/parse.
.consume[void].
.consume[text].
.consume[html].
.consume[json].
.consume[xml].
Consume body using response.text() and set target's outerHTML. This modifier takes precedence over the
.consume modifier and makes it effectless, although if .consume[text] is set, swapped content will be escaped.
Any non-directive HTML attributes on the target will be applied to the swapped content elements.
This modifier automatically triggers a re-render of the replaced element's parent.
%@="listener"
Listen for a dispatched Event
and re-evaluates %http directive before reacting to its Response.
%http directive.
%response and @event directives.
%http directive. As it is re-evaluated, you can however use the $event value to dynamically compute the target URL (e.g.%http="$event ? '/foo' : '/bar'"). All
modifiers from %http directive are inherited, along with the RequestInit prepared by %header and %body directives.
listener only) The dispatched Event.
Response object that contains the fetched data.
response.body
(typing depends on which modifier is used).
@event and %response directives. See their respective documentation for more information.
*once
Render an element once and skip subsequent updates.
*refresh="interval"
Reprocess an element at a specified interval (in seconds).
*for as *refresh will be duplicated for each generated element.
null to stop refreshing.
setTimeout. New calls are scheduled when the directive is processed again, ensuring a consistent interval.
*eval="expression"
Evaluate a JavaScript expression in the context of the element.
*skip
Prevent an element from being processed.
These directives are for development and testing purposes only. They help developers validate features and renderings before production.
Do not use in production environments.
~test="expression"
Special directive for testing purposes.
~test, defaults to Phase.TESTING). The directive will execute during the specified phase before any
other directive in that phase, allowing you to simulate specific scenarios.
textContent with the expression result.
Comment if the expression is truthy, and revert it otherwise.
EvalError if the expression is truthy.
New features that are still in the design phase are published in this package to gather community feedback. These features may undergo significant changes during development and might not be included in the stable release.
Use at your own risk.
*noop
This directive does nothing.
Set up mizu.js in your browser environment using one of two methods:
On the client-side...
.js)This setup automatically starts rendering the page once the script is loaded. It's the simplest way to get started but limited to the default configuration.
<script src="https://mizu.sh/client.js" defer></script>
.mjs)This setup requires you to import and start mizu.js manually, allowing customization of the rendering process, such as setting the initial context and loading additional directives.
<script type="module">
import Mizu from "https://mizu.sh/client.mjs"
await Mizu.render(document.body, { context: { foo: "🌊 Yaa, mizu!" } })
</script>
Looking to effortlessly theme your new web page? Check out matcha.css!
<link rel="stylesheet" href="https://matcha.mizu.sh/matcha.css">
To set up mizu.js in a server environment, install it locally. mizu.js packages are hosted on .
On the server side...
Deno supports the jsr: specifier natively, allowing you to import mizu.js directly.
import Mizu from "jsr:@mizu/render/server"
await Mizu.render(`<div *text="foo"></div>`, { context: { foo: "🌊 Yaa, mizu!" } })
Alternatively, add it to your project using the Deno CLI.
deno add jsr:@mizu/render
Add mizu.js to your project using the JSR npm compatibility layer.
# NodeJS
npx jsr add @mizu/render
# Bun
bunx jsr add @mizu/render
Once installed, use it in your project.
import Mizu from "@mizu/render/server"
await Mizu.render(`<div *text="foo"></div>`, { context: { foo: "🌊 Yaa, mizu!" } })
A HTML attribute recognized by mizu.js which instructs how it should process the element.
The syntax is as follows:
Directives names often begin with special characters to prevent conflicts with standard HTML attributes and to clearly indicate their specific purpose:
* for generic directives.# for directives targeting <slot> elements.
@ for directives related to Event handling.
: for binding HTML attributes.
:: for bi-directional binding.% for HTTP directives.
%@ for combined HTTP and Event directives.~ for testing directives.
Typically, this serves as the directive's argument. At most one tag can be specified per directive.
Modifiers adjust the behavior of the directive. You can specify multiple modifiers on the same directive.
The value of the modifier. The modifier may have an explicit default value, which is used if no value is specified.
The value is validated and cast to the expected type, defaulting if invalid. Modifiers may accept one of the following types:
boolean
, unset defaults to true.
string
, unset defaults to "".
number
, unset defaults to 0.
duration
, unset defaults to 0ms
(supported units: ms, s, m).
Set through the HTML attribute value, it is evaluated asynchronously within the context of the current element during processing.
A directive may have a Default expression, used when no specific expression is provided.
Unless stated otherwise, any JavaScript expression is permitted.
All expressions are evaluated within a specific context, which includes all defined variables and functions. You can define these through the user API or directly via contextual directives.
Certain directives may also provide special variables based on the current processing state, prefixed with a dollar sign ($).
$), it is recommended to avoid this practice to prevent confusion with special variables. In case of a conflict, the special variables will shadow user-defined ones until being shadowed themselves.
__mizu_internal is reserved and cannot be used in expressions.
mizu.js leverages @libs/reactive to monitor context changes and trigger re-renders as needed.
During element processing, all get
operations are cached with the element as a reference. Whenever a set
operation is performed, mizu.js identifies which elements depend on the changed value and re-processes them.
Rendering is the process of evaluating and applying mizu.js directives. This occurs recursively on a subtree and modifies the current DOM.
Each directive is tied to a specific phase, dictating the order of processing. The sequence in which directives appear on an element is irrelevant unless they share the same phase.
Directives within the same phase cannot coexist on the same element unless explicitly allowed to be specified Multiple times.
00
META
01
ELIGIBILITY
02
PREPROCESSING
10
TESTING
11
CONTEXT
21
EXPAND
22
MORPHING
23
TOGGLE
31
HTTP_HEADER
32
HTTP_BODY
33
HTTP_REQUEST
34
HTTP_CONTENT
35
HTTP_INTERACTIVITY
41
CONTENT
42
CONTENT_INTERPOLATION
49
CONTENT_CLEANING
51
ATTRIBUTE
52
ATTRIBUTE_MODEL_VALUE
59
ATTRIBUTE_CLEANING
61
INTERACTIVITY
71
DISPLAY
81
CUSTOM_ELEMENT
82
REFERENCE
89
CUSTOM_PROCESSING
99
POSTPROCESSING
This section is targeted at users who want to use mizu.js rendering and directives.
If you wish to develop custom directives, please refer to the Developer API section instead.
Full API documentation is available at jsr.io/@mizu/render/client.
The following directives are enabled by default in the client-side API. You can customize the enabled directives by creating a custom instance rather than using the default one.
Client.constructor(options?: ClientOptions)
Client constructor.
Client.defaults: Required<ClientOptions>
Client.default: Client
Default Client instance.
Client.context: Record<PropertyKey, any>
Rendering context.
All properties assigned to this object are available during rendering.
Changes to this object are reactive and will trigger a re-render of related elements.
This is achieved using Context, which leverages Proxy handlers.
You cannot reassign this property directly to ensure reactivity is maintained. To achieve a similar effect, use
Object.assign().
Client.render(element: T, options?: ClientRenderOptions) => Promise<T>
Start rendering all subtrees marked with the *mizu attribute.
const mizu = new Client({ context: { foo: "bar" } })
await mizu.render()
Client.flush() => Promise<void>
Flush the reactive render queue of Renderer.
Full API documentation is available at jsr.io/@mizu/render/server.
The following directives are enabled by default in the server-side API. You can customize the enabled directives by creating a custom instance rather than using the default one.
Server.constructor(options?: ServerOptions)
Server constructor.
Server.defaults: Required<ServerOptions>
Server.default: Server
Default Server instance.
Server.context: Record<PropertyKey, any>
Default rendering context.
All properties assigned to this object are accessible during rendering.
Server.render(content: string | Arg<Renderer["render"]>, options?: ServerRenderOptions & Pick<ServerOptions, "warn">) => Promise<string>
Parse an HTML string and render all subtrees.
The *mizu attribute is only required if implicit is set to false.
const mizu = new Server({ context: { foo: "bar" } })
await mizu.render(`<html><body><a ~test.text="foo"></a></body></html>`)
Server.generate(sources: Array<StringSource | GlobSource | CallbackSource | URLSource>, options?: ServerGenerateOptions) => Promise<void>
Generate static files from various sources.
Options:
output: Specify the path to the output directory.clean: Empty the output directory before generating files.Supported sources:
StringSource: Generate content from raw strings.GlobSource: Generate content from local files matching the provided glob patterns.CallbackSource: Generate content from callback returns.URLSource: Generate content from fetched URLs.Each source can be templated using mizu rendering by passing a render option.
const mizu = new Server({ directives: ["@mizu/test"], generate: { output: "/fake/output" } })
await mizu.generate(
[
// Copy content from strings
[ "<p>foo</p>", "string.html" ],
[ "<p ~test.text='foo'></p>", "string_render.html", { render: { context: { foo: "bar" } } } ],
// Copy content from local files
[ "**\/*", "public", { directory: "/fake/static" } ],
[ "*.html", "public", { directory: "/fake/partials", render: { context: { foo: "bar "} } } ],
// Copy content from callback return
[ () => JSON.stringify({ foo: "bar" }), "callback.json" ],
[ () => `<p ~test.text="'foo'"></p>`, "callback.html", { render: { context: { foo: "bar" } } } ],
// Copy content from URL
[ new URL(`data:text/html,<p>foobar</p>`), "url.html" ],
[ new URL(`data:text/html,<p ~test.text="foo"></p>`), "url_render.html", { render: { context: { foo: "bar" } } } ],
],
// No-op: do not actually write files and directories
{ fs: { readdir: () => Promise.resolve([] as string[]), mkdir: () => null as any, write: () => null as any } },
)
This section is targeted at developers who want to create custom mizu.js rendering and directives.
If you wish to render templates, please refer to the User API section instead.
Full API documentation is available at jsr.io/@mizu/internal/engine.
This section covers the Directive interface, essential for creating custom directives. Each built-in directive is also an instance of this interface. It follows the steps outlined in the Rendering concept.
When manipulating the DOM, use the Renderer methods to ensure compatibility between virtual and real DOMs. These methods also provide helpful tools to simplify the creation of custom
directives.
Full API documentation is available at jsr.io/@mizu/internal.
This package includes several APIs used by mizu.js, such as the Renderer, virtual DOM implementations, the testing framework, and more. These symbols are documented in the source code and are intended for development environments.
mizu.js currently follows ZeroVer versioning. This means breaking changes may occur in minor versions, even for previously defined features.
It will eventually stabilize and follow SemVer versioning after more feedback and testing.
Some aspects of mizu.js are not fully defined yet. While these are mentioned in the documentation, they are gathered here for easy reference.
Relying on undefined behavior in your applications is strongly discouraged, as these behaviors may change in future versions without being considered breaking changes. Additionally, any unusual behavior encountered is not considered a bug until properly specified.
If you wish to participate in the design and definition of these features, check out the issues tagged with spec
.