|
1 | | -# Modular OpenScript Framework |
| 1 | +# OpenScriptJs |
2 | 2 |
|
3 | | -A modern, modular, event-driven JavaScript framework built for scalability and maintainability. OpenScript combines the power of **Inversion of Control (IoC)**, **Reactive State Management**, and a **Component-Based Architecture** into a lightweight package with zero runtime dependencies. |
| 3 | +<p align="center"> |
| 4 | + <a href="https://github.com/OpenScriptJs/modular-openscript" target="_blank"> |
| 5 | + <!-- You can add a logo here if available --> |
| 6 | + <img src="https://via.placeholder.com/200x50?text=OpenScriptJs" alt="OpenScriptJs Logo" width="200"> |
| 7 | + </a> |
| 8 | +</p> |
4 | 9 |
|
5 | | -## 🚀 Key Features |
| 10 | +<p align="center"> |
| 11 | + <strong>The Progressive, PHP-Inspired JavaScript Framework for Artisans.</strong> |
| 12 | +</p> |
6 | 13 |
|
7 | | -- **IoC Container**: Centralized dependency management using a robust container and `app()` helper. |
8 | | -- **Reactive State**: Proxy-based state management with automatic UI updates using `state()`. |
9 | | -- **Event-Driven**: Powerful `Broker` and `Mediator` pattern for decoupled communication. |
10 | | -- **Component-Based**: Class-based components with lifecycle hooks and functional stateless components. |
11 | | -- **OpenScript Markup (OSM)**: A powerful DSL for generating HTML without a Virtual DOM overhead. |
12 | | -- **Fluent Router**: Expressive, fluent API for client-side routing with nested routes and grouping. |
13 | | -- **Context API**: Share state globally without prop drilling. |
14 | | -- **Lightweight**: Zero runtime dependencies, pure JavaScript. |
15 | | -- **Vite Integration**: Optimized build process with automatic component discovery. |
| 14 | +<p align="center"> |
| 15 | + <a href="https://www.npmjs.com/package/modular-openscriptjs"><img src="https://img.shields.io/npm/v/modular-openscriptjs.svg?style=flat-square" alt="NPM Version"></a> |
| 16 | + <a href="https://github.com/OpenScriptJs/modular-openscript/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/modular-openscriptjs.svg?style=flat-square" alt="License"></a> |
| 17 | + <a href="https://github.com/OpenScriptJs/modular-openscript/issues"><img src="https://img.shields.io/github/issues/OpenScriptJs/modular-openscript?style=flat-square" alt="Issues"></a> |
| 18 | +</p> |
| 19 | + |
| 20 | +## Introduction |
| 21 | + |
| 22 | +OpenScriptJs is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable, creative experience to be truly fulfilling. OpenScript attempts to take the pain out of development by easing common tasks used in the majority of web projects, such as simple routing, powerful state management, and decoupled event handling. |
| 23 | + |
| 24 | +It combines the best concepts from sophisticated backend architectures—like **Inversion of Control (IoC)** and **Mediator Patterns**—with the modern reactivity of frontend development. The result is a lightweight, zero-dependency framework that scales from small widgets to complex Single Page Applications without the bloat. |
| 25 | + |
| 26 | +## 🚀 Why OpenScriptJs? |
| 27 | + |
| 28 | +We didn't just build another framework; we built a toolset for developers who value structure and clarity. |
| 29 | + |
| 30 | +- **IoC Container**: |
| 31 | + _Why?_ Managing dependencies manually is messy. Our robust container and `app()` helper give you a centralized way to manage your services, promoting loose coupling and testability. |
| 32 | + |
| 33 | +- **Reactive State**: |
| 34 | + _Why?_ UI should be a function of state. Our proxy-based `state()` system automatically updates your DOM when data changes, without the complexity of a Virtual DOM. |
| 35 | + |
| 36 | +- **Event-Driven Architecture**: |
| 37 | + _Why?_ Components shouldn't talk directly to each other; it leads to spaghetti code. Our powerful `Broker` and `Mediator` pattern enables true decoupling. |
| 38 | + |
| 39 | +- **Component-Based**: |
| 40 | + _Why?_ Reusability is key. Build encapsulated functional or class-based components with full lifecycle hooks. |
| 41 | + |
| 42 | +- **OpenScript Markup (OSM)**: |
| 43 | + _Why?_ Context switching between HTML and JS breaks flow. OSM allows you to generate HTML using expressive JavaScript, giving you the full power of the language right in your views. |
| 44 | + |
| 45 | +- **Fluent Router & Context API**: |
| 46 | + _Why?_ Modern apps need robust navigation and global state sharing without "prop drilling". We provide both out of the box. |
| 47 | + |
| 48 | +- **Zero Dependencies**: |
| 49 | + _Why?_ Bloat slows you down. OpenScriptJs is pure, lightweight JavaScript. |
16 | 50 |
|
17 | 51 | --- |
18 | 52 |
|
@@ -468,6 +502,14 @@ export default function Card(title, content, ...args) { |
468 | 502 | } |
469 | 503 | ``` |
470 | 504 |
|
| 505 | +### 💡 Choosing the Right Component Type |
| 506 | + |
| 507 | +- **Use Functional Components** when your component is just receiving data and displaying it. They are lighter, faster, and easier to test. |
| 508 | +- **Use Class Components** when you need: |
| 509 | + - Internal state (toggle buttons, form inputs). |
| 510 | + - Lifecycle hooks (`$_mounted` for API calls or setting up 3rd party libs). |
| 511 | + - Complex event handlers. |
| 512 | + |
471 | 513 | ### Naming Conventions |
472 | 514 |
|
473 | 515 | - **Classes/Functions**: PascalCase (e.g., `UserProfile`). |
@@ -551,6 +593,16 @@ h.button({ onclick: this.method("handleClick") }, "Click"); |
551 | 593 |
|
552 | 594 | OpenScript Markup (OSM) is a powerful, JavaScript-based Domain Specific Language (DSL) for generating HTML. At its core is the `h` proxy service, which translates property accessors into DOM elements. |
553 | 595 |
|
| 596 | +### 💡 Why OSM? |
| 597 | + |
| 598 | +You might ask, "Why not just use HTML or JSX?" |
| 599 | + |
| 600 | +While JSX is popular, it requires a build step. **OSM is pure JavaScript.** |
| 601 | + |
| 602 | +- **No Compilation Required**: It works directly in the browser. |
| 603 | +- **Full Power of JS**: You can use `map`, `filter`, variables, and functions directly within your structure without context switching. |
| 604 | +- **Composition**: Functions can return arrays of elements, making composition trivial. |
| 605 | + |
554 | 606 | ### Basic Usage |
555 | 607 |
|
556 | 608 | You access OSM via the `h` service from the IoC container. |
@@ -732,6 +784,13 @@ h.UserProfile({ |
732 | 784 |
|
733 | 785 | OpenScript uses the `State` class to handle reactive data. When a state's value changes, any dependent components or listeners are automatically notified, triggering UI updates. |
734 | 786 |
|
| 787 | +### ⚡ The Magic of Proxies |
| 788 | + |
| 789 | +OpenScript leverages modern JavaScript **Proxies**. This means you don't need special setter functions like `setState({ count: 1 })` found in other frameworks. You simply assign the value, and the framework handles the rest. |
| 790 | + |
| 791 | +- **Clean Syntax**: `count.value = 5`. That's it. |
| 792 | +- **Micro-Updates**: Only the specific nodes bound to that state update in the DOM. The entire component doesn't necessarily re-render, making it incredibly performant. |
| 793 | + |
735 | 794 | ### Creating State |
736 | 795 |
|
737 | 796 | You create a state object using the `state` helper function. States can hold primitives(strings, numbers, booleans) or objects. |
@@ -833,7 +892,18 @@ count.listener((s) => { |
833 | 892 |
|
834 | 893 | ## 6. Context API |
835 | 894 |
|
836 | | -The Context API provides a mechanism to share state and data across decoupled components and mediators without the need for "prop drilling" (passing data through multiple layers of components). It acts as a shared, central repository for specific domains of your application (e.g., Global, User, Theme). |
| 895 | +The Context API provides a mechanism to share state and data across decoupled components and mediators without the need for "prop drilling" (passing data through multiple layers of components). It acts as a shared, central repository for specific domains of your application. |
| 896 | + |
| 897 | +### 💼 Common Use Cases |
| 898 | + |
| 899 | +Use Context for data that is truly global: |
| 900 | + |
| 901 | +- **User Session**: Is the user logged in? Who are they? |
| 902 | +- **Theme Settings**: Dark mode vs Light mode. |
| 903 | +- **Language/Localization**: Current active language. |
| 904 | +- **Shopping Cart**: Items currently in the cart. |
| 905 | + |
| 906 | +For everything else (form inputs, toggle states), stick to local Component State to keep your app simple. |
837 | 907 |
|
838 | 908 | ### Setup & Definition |
839 | 909 |
|
@@ -1028,13 +1098,21 @@ Once parsed, the `data` object gives you safe ways to access info: |
1028 | 1098 | ## 8. Mediators |
1029 | 1099 |
|
1030 | 1100 | Mediators are the **"Logic Handlers"** of your application. |
1031 | | -In standard frontend frameworks, you might mix your API calls and business logic right inside your UI components. In OpenScript, we separate them. |
1032 | 1101 |
|
1033 | | -**Think of it like a Restaurant:** |
| 1102 | +### 🧠 Philosophy: Separation of Concerns |
1034 | 1103 |
|
1035 | | -- **Component (Waiter)**: Takes the order (Button Click) and sends it to the kitchen. It doesn't cook. |
1036 | | -- **Mediator (Chef)**: Listens for the order, cooks the food (API Call / Logic), and places it on the counter. |
1037 | | -- **Broker (Counter)**: The place where orders and food are exchanged. |
| 1104 | +In many frameworks, business logic often bleeds into UI components, making them hard to read and impossible to test. OpenScript enforces a strict separation: |
| 1105 | + |
| 1106 | +- **Components**: Responsible ONLY for rendering and user interaction. |
| 1107 | +- **Mediators**: Responsible for API calls, data manipulation, and business rules. |
| 1108 | + |
| 1109 | +#### The Restaurant Analogy |
| 1110 | + |
| 1111 | +Think of your application like a busy restaurant: |
| 1112 | + |
| 1113 | +- **Component (Waiter)**: Takes the order (Button Click) and sends it to the kitchen. It doesn't cook anything; it just shouting "Order Up!". |
| 1114 | +- **Mediator (Chef)**: Listens for the order, cooks the food (API Call), and rings the bell when done. |
| 1115 | +- **Broker (Counter)**: The central communication hub where orders are placed and picked up. |
1038 | 1116 |
|
1039 | 1117 | ### 1. Creating a Mediator |
1040 | 1118 |
|
@@ -1276,8 +1354,12 @@ router.default(() => { |
1276 | 1354 |
|
1277 | 1355 | ## 10. IoC Container |
1278 | 1356 |
|
1279 | | -As your app grows, managing connections between everything (Routers, APIs, Settings) becomes messy. |
1280 | | -The **IoC (Inversion of Control) Container** solves this by acting as a "central warehouse" for all your services. |
| 1357 | +As your app grows, managing connections between everything (Routers, APIs, Settings) becomes messy. The **IoC (Inversion of Control) Container** solves this by acting as a "central warehouse" for all your services. |
| 1358 | + |
| 1359 | +### 🏭 Why Inversion of Control? |
| 1360 | + |
| 1361 | +Directly importing dependencies (e.g., `import api from './api'`) creates rigid, hard-to-test code. |
| 1362 | +The IoC container allows you to swap implementations easily. This is excellent for testing: you can inject a "Fake API" when running unit tests without changing a single line of your component code. |
1281 | 1363 |
|
1282 | 1364 | Instead of writing `new ApiService()` everywhere, you simply ask the container: _"Hey, give me the API Service"_ and it hands it to you. |
1283 | 1365 |
|
@@ -1504,7 +1586,41 @@ If a class string gets too long, extract it to CSS using `@apply`. |
1504 | 1586 | } |
1505 | 1587 | ``` |
1506 | 1588 |
|
1507 | | -````javascript |
| 1589 | +```javascript |
1508 | 1590 | h.button({ class: "btn-primary" }, "Click Me"); |
1509 | | -```- **`v(state, cb)`**: Create an anonymous reactive text node. |
1510 | | -```` |
| 1591 | +``` |
| 1592 | + |
| 1593 | +--- |
| 1594 | + |
| 1595 | +## 🤝 Contributing |
| 1596 | + |
| 1597 | +Thank you for considering contributing to the OpenScriptJs framework! The contribution guide works as follows: |
| 1598 | + |
| 1599 | +1. Fork the repository. |
| 1600 | +2. Create your feature branch (`git checkout -b feature/AmazingFeature`). |
| 1601 | +3. Commit your changes (`git commit -m 'Add some AmazingFeature'`). |
| 1602 | +4. Push to the branch (`git push origin feature/AmazingFeature`). |
| 1603 | +5. Open a Pull Request. |
| 1604 | + |
| 1605 | +If you discover a security vulnerability within OpenScriptJs, please send an e-mail to Levi Kamara Zwannah via [levizwannah@gmail.com](mailto:levizwannah@gmail.com). All security vulnerabilities will be promptly addressed. |
| 1606 | + |
| 1607 | +## 🐛 Reporting Bugs |
| 1608 | + |
| 1609 | +If you encounter any bugs or issues, please report them using the [GitHub Issue Tracker](https://github.com/OpenScriptJs/modular-openscript/issues). Please include: |
| 1610 | + |
| 1611 | +- A detailed description of the bug. |
| 1612 | +- Steps to reproduce the behavior. |
| 1613 | +- Expected vs. actual results. |
| 1614 | +- Screenshots or code snippets if applicable. |
| 1615 | + |
| 1616 | +## 📜 License |
| 1617 | + |
| 1618 | +The OpenScriptJs framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). |
| 1619 | + |
| 1620 | +## ✍️ Author |
| 1621 | + |
| 1622 | +OpenScriptJs is a product of **Levi Kamara Zwannah**. |
| 1623 | + |
| 1624 | +--- |
| 1625 | + |
| 1626 | +_Built with ❤️ for developers who love code._ |
0 commit comments