Skip to content

Repository files navigation

Easy.js

Ultra-lightweight frontend framework: HTML / CSS / JS SFCs, no Virtual DOM, surgical DOM updates via compile-time dependency tracking. Runtime and compiler are zero-dependency (esbuild is the only CLI build dependency).

File extension: .easy
Authoring style: Svelte-like (short, clear)
Package: one install — mez-easyjs
Repository: github.com/MoonesMezher/easyjs


Production install

npm i mez-easyjs
# or globally for the CLI
npm i -g mez-easyjs

npx easy create my-app --template starter --yes
cd my-app
npm run dev

Imports

import { createApp, reactive, createRouter, createStore } from 'mez-easyjs';
// same as: from 'mez-easyjs/runtime'
import { compile } from 'mez-easyjs/compiler';

Publish (maintainers)

Do not publish from a dirty tree:

# 1) verify
npm test
npm run pack:check          # dry-run tarball contents

# 2) publish the single package
npm publish -w mez-easyjs --access public

# optional dry-run
npm run publish:dry

Canonical component

<script>
	let count = 0;

	function greet() {
		alert('Welcome to Easy!');
	}

	function inc() {
		count++;
	}
</script>

<button onclick={greet}>click me</button>
<p>{count}</p>
<button onclick={inc}>+</button>

<style>
	button {
		font-size: 2em;
	}
</style>

No <template> wrapper required — markup sits between <script> and <style>. Optional <template> still works for compatibility.


Syntax decisions

Feature Primary syntax Notes
Text {count} Escaped via textContent (XSS-safe)
Raw HTML {@html html} Explicit opt-in only
Events onclick={handler} Compiles to delegated data-e-onnever inline onclick="..."
State let count = 0 Top-level let → reactive
Methods function inc() { count++ } Refs to lets rewritten to state
Two-way bind:value={draft} Also bind:checked
If / each {#if} / {#each list as item} Also e-if / e-for
Types <script lang="ts"> Light type-strip (not full tsc)
Compat {{ }}, @click, export default {…} Still accepted

Packages

Package Role
mez-easyjs Runtime + compiler + CLI (easy / create-easy-app) + templates
examples/demo End-to-end demo

Stable public imports: mez-easyjs / mez-easyjs/runtime and mez-easyjs/compiler (no deep src/… paths in published consumers).


Interoperability

Easy.js is ESM-first and merges cleanly with Vite / Webpack / esbuild / vanilla apps:

import { createApp, reactive, createRouter, createStore } from 'mez-easyjs';
import { compile } from 'mez-easyjs/compiler';
  • Alongside other libs: mount into a dedicated root — createApp(App).mount('#easy-root') — without owning the whole page.
  • CLI: scaffold and build with the easy bin from mez-easyjs; apps depend on the same package for the runtime.
  • Custom pipeline: compile .easy with mez-easyjs/compiler, bundle the JS with your bundler, import runtime helpers from mez-easyjs.
  • TypeScript projects: light .d.ts stubs ship with the package.
  • No globals: production builds do not set window.*. Dev-only flags (window.__EASY_DEV__, HMR, overlay) are injected by easy dev.

Security

Rule Behavior
Default text {expr}textContent (never parses HTML)
Raw HTML {@html expr} or e-html only — intentional XSS surface
Events onclick={fn}data-e-on; quoted onclick="..." rejected
URL attrs href / src / action / … run through sanitizeUrl (blocks javascript:, data:, …)
Dangerous attrs on* and srcdoc cannot be bound or emitted as static HTML
CSP No eval / new Function; no inline handlers

Recommended CSP (adjust nonces/hashes for your host scripts):

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self'; base-uri 'self'; form-action 'self'; object-src 'none'

Notes:

  • 'unsafe-inline' for style may be needed for scoped component CSS injected at runtime. Prefer nonces if you control the style injector.
  • Do not add 'unsafe-eval'.
  • {@html} bypasses escaping — only pass trusted / sanitized HTML.
  • Tailwind Play CDN templates load a third-party script; tighten CSP if you ship that in production.

Verify:

npm run test:security

Monorepo quick start

npm install
npm run create              # scaffold (uses file: links inside this repo)
npm run dev                 # → http://localhost:5173/
npm run build
npm test                    # security + reactivity

Scaffold (easy create)

npm run create -- my-app --template starter --yes
npx create-easy-app my-app --template tailwind --yes
Template What you get
minimal Skeleton + App.easy
starter Counter, routing, props
tailwind Same + Tailwind Play CDN (no PostCSS / npm tailwindcss)

Inside this monorepo, create rewrites deps to file:…/packages/easyjs. Published users get "mez-easyjs": "^0.1.0".

CLI

easy create [name]              Interactive project wizard
create-easy-app [name]          Same wizard (npm bin alias)
easy create my-app --template starter --yes
easy dev [--port 5173] [--cwd]  Dev server + HMR + error overlay
easy build [--outDir dist]      Vite-like dist/ (assets/*.js + *.css, minified)
easy generate component Counter
easy generate page About

Production build

npm run build
# or: easy build --cwd examples/demo
dist/
  index.html
  assets/
    index-<hash>.js
    index-<hash>.css
    chunk-<name>-<hash>.js

Serve dist/ with any static host (npx serve dist).


Arabic summary / ملخص عربي

Easy.js إطار خفيف بدون Virtual DOM بكتابة شبيهة بـ Svelte: {count} و onclick={fn} بدون <template> إلزامي. حزمة واحدة (mez-easyjs) تشمل runtime و compiler و CLI. يدعم HMR مع حفظ الحالة، وحماية XSS لملفات .easy.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages