@medyll/idae-html
v1.0.3
Published
Raw HTML utility library for dynamic web apps/sites (client & client-server), inspired by Svelte/React but builderless. Provides advanced HTML generation, parsing, and manipulation in JS/TS. Integrates with @medyll/idae-dom-events, idae-idbql, and @medyll
Maintainers
Readme
idae-html
Package Manager: This package is part of the Idae monorepo, which uses pnpm for dependency and script management. Use pnpm install, pnpm run, etc. to ensure consistency.
Overview
idae-html provides utilities and helpers for HTML generation, parsing, and manipulation in JavaScript/TypeScript projects. It is designed to be used both in browser and Node.js environments.
Monorepo Dependencies
@medyll/idae-dom-events: DOM event helpers and advanced event-driven logic (seesrc/lib/main.ts).idae-idbql: IndexedDB query layer for client-side persistence (used in advanced scenarios; see monorepo for details).@medyll/idae-stator: state management and reactivity utilities (used for advanced stateful UI/data flows; see monorepo for usage patterns).
Features
- HTML string generation and templating
- Safe escaping and sanitization helpers
- DOM parsing and manipulation utilities
- Integrates with other Idae packages for UI, data flow, and state management
Persistence (IndexedDB)
This package exposes optional helpers that integrate with the monorepo's IndexedDB query layer @medyll/idae-idbql when that package is available in the workspace/runtime. The core runtime (core) will provide the following helpers when idae-idbql is present:
core.createIdbqDb(model, version)— create an IndexedDB instance for the given model and version.core.createIdbqlState(idbqlInstance, options)— create a reactive state surface for use in UI examples.core.idbql— passthrough to the idbql API when available.
These helpers are optional: idae-html will still work without idae-idbql installed, but persistence-related helpers will be undefined.
Example (browser/demo usage):
import { core } from '/packages/idae-html/src/lib/core-engine.js';
// minimal model example
const model = {
notes: { keyPath: '++id, created_at' }
};
// create DB (if helper is present)
if (core.createIdbqDb) {
const store = core.createIdbqDb(model, 1);
const { idbql, idbqlState } = store.create('demo-db');
// add a note
idbql.notes.add({ content: 'hello', created_at: Date.now() });
// reactive state (optional)
if (core.createIdbqlState) {
const state = core.createIdbqlState(idbql);
// use state in examples or derived UI
}
}Usage
Import the required helpers from the package:
import { html, escapeHtml, parseHtml } from '@medyll/idae-html';
const markup = html`<div>${escapeHtml(userInput)}</div>`;
const dom = parseHtml(markup);Server-side slots and slot convention
idae-html supports a lightweight server-side slot model designed to work with template fragments that may be fetched and composed on the server.
Convention used by the server runtime:
- Caller (the page requesting/inserting a component) provides slot content as
divelements with adata-slotattribute, e.g.<div data-slot="header">...content...</div>. - Callee (the fetched template/component) exposes placeholders using standard shadow-style slots:
<slot name="header">fallback</slot>.
Key behaviors and notes:
- Unnamed/default slots: caller-provided slots that are not explicitly named (or whose
data-slotvalue is empty/whitespace) are normalized to the key"default". On the callee side,<slot>(withoutname) is treated the same as<slot name="default">when server-side slot application runs. This ensures the common usage patterns below map correctly:- Caller examples that map to the same slot:
<div data-slot>content</div>,<div data-slot="default">content</div>, or an unnamed wrapper element. - Callee examples that are equivalent:
<slot></slot>and<slot name="default"></slot>.
- Caller examples that map to the same slot:
- Application: runtime helpers such as
collectSlotsFromHtmlandapplyServerSlotsToHtmlperform this normalization. By default applied string slot values are escaped; setallowHtml: trueto allow raw HTML insertion for trusted content.
Helpers:
core.renderHtmlWithSlots(template, slots, options)— renders a template containing<slot>placeholders.slotsis a map where keys are slot names and values are strings or Nodes. By default string values are escaped; setoptions.allowHtml=trueto treat strings as trusted HTML.
Compatibility & tests:
- A set of small compatibility wrappers expose server helpers under
scripts/*.jswhile the canonical implementation lives inscripts/server/*(this keeps tests and legacy tooling stable). - The repository contains unit/integration tests covering slot collection and application (see
test/integration-server-slots.test.js). After the recent normalization change, tests pass locally.
Security: caller-provided slot HTML is appended verbatim to the processed template. By default strings are escaped when applied via runtime helpers; avoid allowHtml: true for untrusted content.
Components registry
This package provides a small, opinionated registry for initialising HTML components in demos and pages.
- Register an initializer:
core.registerComponent(name, spec)—specmay be either a function (legacy) or an object{ script: (root)=>{}, style?: string, meta?: {...} }.- If
specis a function it is treated as thescriptinitializer for backwards compatibility. - The recommended, normative shape is an object with a
scriptproperty:
- If
core.registerComponent('dropdown', {
script(root){
// initializer runs with the component root element
},
style: '/* optional component-level CSS string to inject */',
meta: { author: 'you' }
});- Mark component roots in markup with
data-component="<name>"and scope runtime selectors inside the component root to avoid global IDs. - Helpers:
core.initComponent(name, root?),core.initRegisteredComponents(root?),core.autoInitRegisteredComponents(). - Example:
<div data-component="dropdown">
<button data-trigger>Open</button>
<div data-menu>...</div>
</div>
<script type="module">
import { core } from '/packages/idae-html/src/lib/core-engine.ts';
core.registerComponent('dropdown', {
script(root){
// init dropdown inside `root`
}
});
</script>Using data-component keeps components composable and avoids global ID collisions in examples.
CSSS support (lang="csss")
Component <style> blocks may declare lang="csss". During build the scripts will attempt to compile csss to plain CSS using the local idae-csss module and emit standard <style> in the built output. If the compiler is unavailable or fails, the original contents are emitted as-is.
If you author component styles using the csss syntax, add lang="csss" to the <style> tag in component HTML files (examples updated in src/lib/components).
Build & Test
- Build:
pnpm run build - Test:
pnpm run test - Lint/format:
pnpm run lint && pnpm run format
Contributing
- Follow the monorepo conventions for code style and commit messages.
- Add tests for new features or bug fixes.
- See the monorepo root README for more details.
For more, see the monorepo documentation or contact the maintainers.
Author: Lebrun Meddy (@medyll)
Architecture
flowchart LR
Input[Template / Data] --> Engine[HTML Generator]
Engine --> Sanitizer[Sanitization]
Sanitizer --> Output[HTML String]