mancha
Version:
Javscript HTML rendering engine
220 lines (219 loc) • 9.52 kB
TypeScript
//#region src/store.d.ts
/**
* Internal store properties that are always present. These are managed by the framework
* and should not be set directly by users.
*/
type InternalStoreState = {
/** Reference to the parent store in a hierarchy. */
$parent?: SignalStore;
/** Reference to the root renderer instance. */
$rootRenderer?: SignalStore;
/** Reference to the root DOM node. */
$rootNode?: Node;
} & {
[key: `$$${string}`]: string | null;
};
/**
* Base type for user-defined store state. Uses `any` intentionally to allow flexible
* user-defined state types without requiring explicit index signatures.
*/
type StoreState = Record<string, any>;
/** Type for expression evaluation function. */
type EvalFunction = (thisArg: SignalStoreProxy, args: Record<string, unknown>) => unknown;
/**
* Internal proxy type used within the store implementation. Uses `any` for dynamic property access.
*/
type SignalStoreProxy = SignalStore & InternalStoreState & {
[key: string]: any;
};
type Observer<T> = (this: SignalStoreProxy) => T;
type KeyValueHandler = (this: SignalStoreProxy, key: string, value: unknown) => void;
declare abstract class IDebouncer {
timeouts: Map<(...args: unknown[]) => unknown, ReturnType<typeof setTimeout>>;
debounce<T>(millis: number, callback: () => T | Promise<T>): Promise<T>;
}
/** Default debouncer time in millis. */
declare class SignalStore<T extends StoreState = StoreState> extends IDebouncer {
protected readonly evalkeys: string[];
protected readonly expressionCache: Map<string, EvalFunction>;
protected readonly observers: Map<string, Set<Observer<unknown>>>;
protected readonly keyHandlers: Map<RegExp, Set<KeyValueHandler>>;
protected _observer: Observer<unknown> | null;
readonly _store: Map<string, unknown>;
_lock: Promise<void>;
constructor(data?: T);
private wrapFunction;
private wrapObject;
watch<T>(key: string, observer: Observer<T>): void;
addKeyHandler(pattern: RegExp, handler: KeyValueHandler): void;
notify(key: string, debounceMillis?: number): Promise<void>;
get<T>(key: string, observer?: Observer<T>): unknown;
set(key: string, value: unknown): Promise<void>;
del(key: string): Promise<void>;
keys(): string[];
/**
* Checks if a key exists in THIS store only (not ancestors).
* Use `get(key) !== null` to check if a key exists anywhere in the chain.
*/
has(key: string): boolean;
effect<T>(observer: Observer<T>): T;
private proxify;
get $(): SignalStore<T> & InternalStoreState & T;
/**
* Creates an evaluation function for the provided expression.
* @param expr The expression to be evaluated.
* @returns The evaluation function.
*/
private makeEvalFunction;
/**
* Retrieves or creates a cached expression function for the provided expression.
* @param expr - The expression to retrieve or create a cached function for.
* @returns The cached expression function.
*/
private cachedExpressionFunction;
eval(expr: string, args?: Record<string, unknown>): unknown;
/**
* Executes an async function and returns a reactive state object that tracks the result.
*
* @param fn - The async function to execute.
* @param options - Optional arguments to pass to the function.
* @returns A reactive state object with $pending, $result, and $error properties.
*
* @example
* // In :data attribute - executes on mount
* :data="{ users: $resolve(api.listUsers) }"
*
* // With options
* :data="{ user: $resolve(api.getUser, { path: { id: userId } }) }"
*
* // In :on:click - executes on click
* :on:click="result = $resolve(api.deleteUser, { path: { id } })"
*/
$resolve<T, O = unknown>(fn: (options?: O) => Promise<T>, options?: O): {
$pending: boolean;
$result: T | null;
$error: Error | null;
};
}
//#endregion
//#region src/renderer.d.ts
/**
* Represents an abstract class for rendering and manipulating HTML content.
* Extends the `ReactiveProxyStore` class.
*
* @template T - The type of the store state. Defaults to `StoreState`.
*/
declare abstract class IRenderer<T extends StoreState = StoreState> extends SignalStore<T> {
abstract readonly impl: string;
protected debugging: boolean;
protected readonly dirpath: string;
readonly _skipNodes: Set<Node>;
readonly _customElements: Map<string, Node>;
abstract parseHTML(content: string, params?: ParserParams): Document | DocumentFragment;
abstract serializeHTML(root: DocumentFragment | Node): string;
abstract createElement(tag: string, owner?: Document | null): Element;
abstract createComment(content: string, owner?: Document | null): Node;
abstract textContent(node: Node, tag: string): void;
/**
* Sets the debugging flag for the current instance.
*
* @param flag - The flag indicating whether debugging is enabled or disabled.
* @returns The current instance of the class.
*/
debug(flag: boolean): this;
/**
* Fetches the remote file at the specified path and returns its content as a string.
* @param fpath - The path of the remote file to fetch.
* @param params - Optional parameters for the fetch operation.
* @returns A promise that resolves to the content of the remote file as a string.
*/
fetchRemote(fpath: string, params?: RenderParams): Promise<string>;
/**
* Fetches a local path and returns its content as a string.
*
* @param fpath - The file path of the resource.
* @param params - Optional render parameters.
* @returns A promise that resolves to the fetched resource as a string.
*/
fetchLocal(fpath: string, params?: RenderParams): Promise<string>;
/**
* Preprocesses a string content with optional rendering and parsing parameters.
*
* @param content - The string content to preprocess.
* @param params - Optional rendering and parsing parameters.
* @returns A promise that resolves to a DocumentFragment representing the preprocessed content.
*/
preprocessString(content: string, params?: RenderParams & ParserParams): Promise<Document | DocumentFragment>;
/**
* Preprocesses a remote file by fetching its content and applying preprocessing steps.
* @param fpath - The path to the remote file.
* @param params - Optional parameters for rendering and parsing.
* @returns A Promise that resolves to a DocumentFragment representing the preprocessed content.
*/
preprocessRemote(fpath: string, params?: RenderParams & ParserParams): Promise<Document | DocumentFragment>;
/**
* Preprocesses a local file by fetching its content and applying preprocessing steps.
* @param fpath - The path to the local file.
* @param params - Optional parameters for rendering and parsing.
* @returns A promise that resolves to the preprocessed document fragment.
*/
preprocessLocal(fpath: string, params?: RenderParams & ParserParams): Promise<Document | DocumentFragment>;
/**
* Creates a subrenderer from the current renderer instance.
* @returns A new instance of the renderer with the same state as the original.
*/
subrenderer(): IRenderer;
/**
* Logs the provided arguments if debugging is enabled.
* @param args - The arguments to be logged.
*/
log(...args: unknown[]): void;
/**
* Preprocesses a node by applying all the registered preprocessing plugins.
*
* @template T - The type of the input node.
* @param {T} root - The root node to preprocess.
* @param {RenderParams} [params] - Optional parameters for preprocessing.
* @returns {Promise<T>} - A promise that resolves to the preprocessed node.
*/
preprocessNode<T extends Document | DocumentFragment | Node>(root: T, params?: RenderParams): Promise<T>;
/**
* Renders the node and applies all the registered rendering plugins.
*
* @template T - The type of the root node (Document, DocumentFragment, or Node).
* @param {T} root - The root node to render.
* @param {RenderParams} [params] - Optional parameters for rendering.
* @returns {Promise<T>} - A promise that resolves to the fully rendered root node.
*/
renderNode<T extends Document | DocumentFragment | Node>(root: T, params?: RenderParams): Promise<T>;
/**
* Mounts the Mancha application to a root element in the DOM.
*
* @param root - The root element to mount the application to.
* @param params - Optional parameters for rendering the application.
* @returns A promise that resolves when the mounting process is complete.
*/
mount(root: Document | DocumentFragment | Node, params?: RenderParams): Promise<void>;
}
//#endregion
//#region src/interfaces.d.ts
interface ParserParams {
/** Whether the file parsed is a root document, or a document fragment. */
rootDocument?: boolean;
/** Encoding to use when processing local files. */
encoding?: "ascii" | "utf8";
}
/** The RendererParams interface defines the parameters that can be passed to the renderer. */
interface RenderParams {
/** The current directory of the file being rendered. */
dirpath?: string;
/** Maximum level of recursion allowed when resolving includes. */
maxdepth?: number;
/** Cache policy used when resolving remote paths. */
cache?: RequestCache | null;
/** Whether the current node is the root used in Mancha.moun(...). */
rootNode?: Node;
}
type RendererPlugin = (this: IRenderer, node: ChildNode, params?: RenderParams) => void | Promise<void>;
//#endregion
export { StoreState as a, IRenderer as i, RenderParams as n, RendererPlugin as r, ParserParams as t };