Update README.md for Gefest. And.. I meant at the last commit: I got tired for describing all changes

This commit is contained in:
FullGreaM 2026-04-28 03:12:31 +03:00
parent a4c5b441f6
commit 56a5639c57

View File

@ -1,361 +1,100 @@
# Gefest Framework
Gefest is a lightweight, TypeScript-based framework for building and managing HTML elements programmatically. It provides a class-based approach to create reusable UI components with built-in support for attributes, classes, styles, and event handling.
Gefest is a lightweight TypeScript framework for building HTML UI components with a class-based API. It makes it easy to create reusable elements, bind events, manage styles and classes, and rerender elements dynamically.
## Features
## Overview
- **Class-based Element Creation**: Define HTML elements as TypeScript classes
- **Attribute Management**: Easy setting, getting, and removing of HTML attributes with reserved attribute validation
- **CSS Class Handling**: Add and remove classes dynamically with full control over class lists
- **Style System**: Extensible styling with custom style classes and inline personal styles
- **Event Handling**: Multiple event listeners with custom event emission and data passing
- **Element Registration**: Automatic ID generation and DOM integration with unique identifiers
- **Primitive Components**: Pre-built HTML element wrappers for common elements
- **Dynamic Updates**: Re-render elements on the fly with automatic DOM synchronization
- **HTML Parsing**: Convert HTML strings to Gefest elements with `fromHTML()`
- **Personal Inline Styling**: Set and manage inline CSS styles directly on elements
- **Async Event System**: Promise-based event handling with custom event data
Gefest provides:
- A base `GefestElement` class for elements with nested content and attributes
- Automatic `data-gefest-id` registration for DOM element tracking
- Class and style management via helper methods
- Event handling with `onClick`, `on`, `once`, and `emit`
- Expression of UI elements as TypeScript classes instead of raw HTML strings
- A simple engine that binds click handlers and supports rerendering
## Installation
Gefest is included as a module in this project. To use it in your TypeScript files:
```typescript
import { GefestEngine, GefestElement } from './engine';
import { GefestButton } from './primitives/button';
// ... other imports as needed
```
## Core Concepts
### GefestElement
The base abstract class for all Gefest elements. It provides:
- Content management (strings or nested elements)
- Attribute handling
- Class management
- Style application
- Event binding
- Automatic re-rendering on updates
### GefestEngine
Manages the lifecycle of Gefest elements:
- Registers elements with unique IDs
- Activates event handlers on DOM elements
- Provides the main entry point for applications
- Handles re-rendering of updated elements
### GefestStyle
Abstract base class for styling systems. Implement custom styles by extending this class.
## Basic Usage
### Creating Elements
```typescript
import { GefestButton } from './primitives/button';
// Create a simple button
const button = new GefestButton("Click me!");
console.log(button.build()); // <button data-gefest-id="gefest-abc123">Click me!</button>
```
### Setting Attributes
```typescript
const button = new GefestButton("Submit");
button.setAttribute('type', 'submit');
button.setAttribute('disabled', 'true');
```
### Managing Classes
```typescript
const button = new GefestButton("Button");
button.addClass('btn');
button.addClass('btn-primary');
button.removeClass('btn');
console.log(button.getClassList()); // ['btn-primary']
```
### Hiding Elements
```typescript
const button = new GefestButton("Hidden Button");
button.isHidden = true; // Sets the 'hidden' attribute on the element
```
### Event Handling
```typescript
const button = new GefestButton("Click me!");
button.onClick = () => {
console.log('Button clicked!');
// The framework automatically re-renders after click
};
```
### Updating Elements
```typescript
const button = new GefestButton("Initial");
button.update(); // Re-renders the element in the DOM
```
### Running the Application
## Quick Start
```typescript
import { GefestEngine } from './engine';
import { GefestButton } from './primitives/button';
async function main() {
// Create and configure your elements here
const button = new GefestButton("Hello World");
button.onClick = () => alert('Hello!');
const button = new GefestButton('Click me');
button.addClass('btn');
button.onClick = () => {
alert('Button clicked');
};
// Insert into DOM
document.body.innerHTML = button.build();
}
GefestEngine.main(main);
```
## Core Concepts
### GefestElement
The base class for all Gefest components. It handles:
- Content rendering from strings or nested `GefestElement` instances
- HTML attributes and reserved attribute protection
- CSS class list management
- Inline personal styles
- Event registration and emission
- Unique element registration via `GefestEngine`
- Automatic rerendering when `update()` is called
### GefestEngine
The runtime engine that manages registered elements.
- `register(element)` assigns a unique `data-gefest-id`
- `activateOnClick()` binds click handlers for registered elements
- `main(mainFn)` runs your app and activates click bindings
- `render(gefestId)` rerenders one or all registered elements
### GefestStyle
A base class for custom styling strategies. Extend `GefestStyle` and implement `applyStyle(html, element)` to transform rendered HTML.
## Primitives
Gefest includes several pre-built primitive elements:
### GefestButton
Wraps HTML `<button>` elements.
```typescript
const button = new GefestButton("Click me");
button.setAttribute('type', 'submit');
```
### GefestA
Wraps HTML `<a>` elements.
```typescript
const link = new GefestA("Visit site", "https://example.com");
link.setAttribute('target', '_blank');
```
### GefestImg
Wraps HTML `<img>` elements.
```typescript
const image = new GefestImg("", "path/to/image.jpg");
image.setAttribute('alt', 'Description');
```
### Other Primitives
- `GefestP`: Paragraph (`<p>`)
- `GefestSpan`: Span (`<span>`)
- `GefestHeader`: Header (`<h1>`)
- `GefestI`: Italic (`<i>`)
- `GefestSmall`: Small text (`<small>`)
- `GefestCenter`: Centered content (`<center>`)
## Advanced Features
### Nested Elements
```typescript
const link = new GefestA("Read more", "#");
const button = new GefestButton([link, " about this"]);
```
### Custom Elements
Create your own elements by extending `GefestElement`:
```typescript
import { GefestElement } from './element';
export class GefestDiv extends GefestElement {
protected wrapHTML(content: string): string {
const attrString = this.attributesToString();
return `<div ${attrString}>${content}</div>`;
}
}
```
### Custom Styles
Implement custom styling by extending `GefestStyle`:
```typescript
import { GefestStyle, GefestElement } from './style';
export class BootstrapStyle extends GefestStyle {
applyStyle(html: string, element?: GefestElement): string {
// Apply Bootstrap classes or inline styles
if (element?.getClassList().includes('btn')) {
return html.replace('<button', '<button class="btn btn-primary"');
}
return html;
}
}
```
Apply styles to elements:
```typescript
const button = new GefestButton("Styled Button");
button.style = new BootstrapStyle();
```
### Parsing HTML
Convert existing HTML strings to Gefest elements:
```typescript
const element = GefestElement.fromHTML('<button class="btn">Click</button>');
```
### Personal Styling
Set inline styles directly on elements:
```typescript
const button = new GefestButton("Styled");
button.setPersonalStyle('background-color: blue; color: white; padding: 10px;');
```
Remove personal styles:
```typescript
button.setPersonalStyle(null); // Removes inline styles
```
### Event System
#### Using onClick Handler
```typescript
const button = new GefestButton("Click me");
button.onClick = () => {
console.log('Button was clicked!');
};
```
#### Registering Multiple Event Listeners
Use the `on()` method to register multiple event handlers for the same event:
```typescript
const button = new GefestButton("Multi-Listener");
// First listener
button.on("onClick", (data) => {
console.log('Handler 1 called', data);
});
// Second listener
button.on("onClick", (data) => {
console.log('Handler 2 called', data);
});
```
#### Registering One-Time Event Listeners
Use the `once()` method to register an event handler that only fires once:
```typescript
const button = new GefestButton("One-Time");
// This handler will only execute on the first click
button.once("onClick", (data) => {
console.log('First click only!', data);
// Handler is automatically removed after first execution
});
```
#### Emitting Events
Emit custom events with optional data:
```typescript
const button = new GefestButton("Action");
button.on("onClick", (data) => {
console.log('Click event with data:', data);
});
button.onClick = () => {
// onClick handler is automatically emitted with event data
button.emit("onClick", { timestamp: Date.now(), action: 'clicked' });
};
```
### Element Re-rendering
Trigger manual re-renders when element state changes:
```typescript
const button = new GefestButton("Click me");
let clickCount = 0;
button.onClick = () => {
clickCount++;
// Update content or attributes
button.update(); // Re-renders in the DOM
};
```
### Attribute Management
Full control over element attributes:
```typescript
const button = new GefestButton("Submit");
// Set attribute
button.setAttribute('type', 'submit');
button.setAttribute('aria-label', 'Submit form');
// Get attribute
const type = button.getAttribute('type'); // 'submit'
// Remove attribute
button.removeAttribute('disabled');
// Check for reserved attributes (will throw error)
// button.setAttribute('class', 'btn'); // Error: 'class' is reserved
```
Gefest ships with simple element wrappers:
- `GefestButton``<button>`
- `GefestA``<a>`
- `GefestImg``<img>`
- `GefestP``<p>`
- `GefestSpan``<span>`
- `GefestHeader``<h1>``<h6>`
- `GefestI``<i>`
- `GefestSmall``<small>`
- `GefestCenter``<center>`
## API Reference
### GefestElement
#### Properties
- `gefestId: string` - Unique identifier for the element (readonly)
- `style: GefestStyle | null` - Style to apply to the element
- `onClick: (() => void) | null` - Click event handler (getter/setter)
- `isHidden: boolean` - Whether the element should be hidden (sets the 'hidden' attribute when true)
- `gefestId: string` — auto-generated unique identifier
- `style: GefestStyle | (() => GefestStyle) | null`
- `onClick: (() => void) | null`
- `isHidden: boolean`
- `id: string | null`
#### Methods
- `constructor(content: (GefestElement | string)[] | string)`
- `constructor(content?: (GefestElement | string)[] | string)`
- `build(isFromStyle?: boolean): string`
- `update(): void` - Re-renders the element in the DOM
- `setAttribute(key: string, value: string): void`
- `getAttribute(key: string): string | undefined`
- `removeAttribute(key: string): void`
- `addClass(className: string): void`
- `removeClass(className: string): void`
- `update(): void`
- `setAttribute(key, value): void`
- `getAttribute(key): string | undefined`
- `removeAttribute(key): void`
- `addClass(className): void`
- `removeClass(className): void`
- `getClassList(): string[]`
- `setPersonalStyle(style: string | null): void` - Set inline styles on the element
- `emit(event: GefestElementEvents, data?: unknown): void` - Emit custom events
- `on(event: GefestElementEvents, handler: (data: unknown) => void): void` - Register event listener
- `once(event: GefestElementEvents, handler: (data: unknown) => void): void` - Register one-time event listener
- `checkReservedAttribute(key: string): void` - Validate if attribute key is reserved
- `setPersonalStyle(style: string | null): void`
- `emit(event, data?): void`
- `on(event, handler): void`
- `once(event, handler): void`
- `checkReservedAttribute(key): void`
#### Static Methods
- `fromHTML(html: string): GefestElement`
@ -366,69 +105,132 @@ button.removeAttribute('disabled');
- `register(element: GefestElement): string`
- `activateOnClick(): Promise<void>`
- `main(main: () => Promise<void>): Promise<void>`
- `reRenderByGI(gefestId: string): void`
- `render(gefestId?: string | string[] | null): void`
### GefestStyle
#### Methods
- `applyStyle(html: string, element?: GefestElement): string`
## Examples
## Usage Examples
### Complete Application
### Create a button
```typescript
import { GefestEngine } from './engine';
import { GefestButton, GefestP } from './primitives';
import { GefestButton } from './primitives/button';
async function main() {
const title = new GefestP("Welcome to Gefest!");
title.addClass('title');
const button = new GefestButton('Submit');
button.addClass('btn');
button.setAttribute('type', 'submit');
button.onClick = () => {
console.log('clicked');
};
```
const button = new GefestButton("Get Started");
button.addClass('start-btn');
button.onClick = () => {
alert('Welcome!');
};
### Apply inline styles
// For custom elements, define them as shown above
const container = new (class extends GefestElement {
```typescript
button.setPersonalStyle('background-color: blue; color: white; padding: 10px;');
```
### Hide an element
```typescript
button.isHidden = true;
```
### Nested elements
```typescript
import { GefestA } from './primitives/a';
const link = new GefestA('Read more', '#');
const button = new GefestButton([link, ' more']);
```
### Custom element
```typescript
import { GefestElement } from './element';
class GefestDiv extends GefestElement {
protected wrapHTML(content: string): string {
const attrString = this.attributesToString();
return `<div ${attrString}>${content}</div>`;
}
})([title, button]);
container.addClass('container');
}
```
document.body.innerHTML = container.build();
### Custom style
```typescript
import { GefestStyle } from './style';
class BootstrapStyle extends GefestStyle {
applyStyle(html: string, element?: GefestElement): string {
if (element?.getClassList().includes('btn')) {
return html.replace('<button', '<button class="btn btn-primary"');
}
return html;
}
}
button.style = new BootstrapStyle();
```
### Event listeners
```typescript
button.on('onClick', (data) => {
console.log('click data', data);
});
button.once('onClick', () => {
console.log('once only');
});
button.onClick = () => {
button.emit('onClick', { value: 1 });
};
```
### Rerendering
```typescript
button.update();
```
### Complete app
```typescript
import { GefestEngine } from './engine';
import { GefestButton, GefestHeader, GefestP } from './primitives';
async function main() {
const title = new GefestHeader('Welcome', 2);
const button = new GefestButton('Start');
button.onClick = () => alert('Hello');
document.body.innerHTML = title.build() + button.build();
}
GefestEngine.main(main);
```
### Form Creation
## Notes
```typescript
import { GefestButton } from './primitives/button';
const submitBtn = new GefestButton("Submit");
submitBtn.setAttribute('type', 'submit');
submitBtn.addClass('btn-submit');
const form = document.createElement('form');
form.innerHTML = submitBtn.build();
document.body.appendChild(form);
```
- `class`, `style`, and `data-gefest-id` are reserved.
- Use `addClass` / `removeClass` for CSS classes.
- Use `setPersonalStyle` for inline styles.
- `GefestElement.fromHTML()` is experimental and may not preserve all behavior.
## Contributing
To add new primitives or extend the framework:
1. Create new classes extending `GefestElement`
2. Implement the `wrapHTML` method to return the appropriate HTML tag
3. Add event handling if needed
4. Test with `GefestEngine.main()`
To extend Gefest:
1. Add a class extending `GefestElement`
2. Implement `wrapHTML()` with the desired tag
3. Add custom logic, classes, or events
4. Test with `GefestEngine.main()` in the browser
## License
This framework is part of the AmeVox project. See project license for details.
This framework is part of the AmeVox project. See the project license for details.