Système de plugins OntoWave
OntoWave offre une architecture de plugins extensible qui permet d’injecter du comportement personnalisé à chaque étape du cycle de vie de l’application.
Concepts clés
Un plugin est un objet JavaScript qui implémente une ou plusieurs méthodes de cycle de vie :
| Hook |
Moment d’appel |
Signature |
onStart(ctx) |
Démarrage de l’appli |
(ctx: PluginContext) => void | Promise<void> |
onStop() |
Arrêt de l’appli |
() => void | Promise<void> |
beforeRender(md, route) |
Avant le rendu Markdown |
(md: string, route: string) => string | Promise<string> |
afterRender(html, route) |
Après l’injection du HTML |
(html: string, route: string) => void | Promise<void> |
onRouteChange(route) |
Changement de route |
(route: string) => void | Promise<void> |
Créer un plugin
const monPlugin = {
name: 'mon-plugin', // obligatoire, unique
version: '1.0.0', // optionnel
onStart(ctx) {
console.log('[mon-plugin] Démarrage', ctx.config)
},
beforeRender(md, route) {
// Ajouter une bannière en haut de chaque page
return `> 🔖 Route : ${route}\n\n` + md
},
afterRender(html, route) {
console.log('[mon-plugin] HTML rendu pour', route, '—', html.length, 'octets')
},
onRouteChange(route) {
console.log('[mon-plugin] Navigation vers', route)
},
onStop() {
console.log('[mon-plugin] Arrêt')
},
}
Enregistrer des plugins
Utilisez createPluginManager() pour gérer vos plugins, puis passez-les à createApp() :
import { createApp, createPluginManager } from 'ontowave'
const plugins = createPluginManager()
.use(monPlugin)
.use(autrePlugin)
const app = createApp({
// ... autres dépendances ...
plugins: plugins.getPlugins(),
})
await app.start()
Exemples de plugins intégrables
Plugin de journalisation
const loggerPlugin = {
name: 'logger',
onRouteChange(route) {
console.log('[logger] Route :', route)
},
afterRender(_html, route) {
console.log('[logger] Rendu terminé :', route)
},
}
Plugin de méta-données analytiques
const analyticsPlugin = {
name: 'analytics',
onRouteChange(route) {
// Envoi vers un service d'analyse
navigator.sendBeacon('/track', JSON.stringify({ page: route, ts: Date.now() }))
},
}
Plugin de transformation Markdown
const badgePlugin = {
name: 'badge',
beforeRender(md) {
// Remplace [[badge:nouveau]] par un span HTML coloré
return md.replace(/\[\[badge:([^\]]+)\]\]/g,
(_, label) => `<span class="badge">${label}</span>`)
},
}
Plugin de mise en évidence de route active
const activeNavPlugin = {
name: 'active-nav',
onRouteChange(route) {
document.querySelectorAll('nav a').forEach(a => {
a.classList.toggle('active', a.getAttribute('href') === `#${route}`)
})
},
}
API de référence
createPluginManager()
Retourne un PluginManager avec les méthodes :
register(plugin) — enregistre un plugin (avertissement si doublon)
use(plugin) — enregistre et retourne le manager (chaînable)
getPlugins() — retourne le tableau des plugins enregistrés
Interface PluginContext
Disponible dans onStart(ctx) :
ctx.config — la configuration complète de l’application (AppConfig)
ctx.navigate(path) — navigue programmatiquement vers un chemin
Limites connues
- Les hooks
beforeRender sont exécutés en séquence : l’ordre d’enregistrement importe
afterRender reçoit le HTML avant les transformations DOM (Mermaid, Kroki, etc.)
- Un plugin doit avoir un
name unique — les doublons sont ignorés avec avertissement console
OntoWave Plugin System
OntoWave provides an extensible plugin architecture that allows injecting custom behavior at every stage of the application lifecycle.
Key Concepts
A plugin is a JavaScript object that implements one or more lifecycle methods:
| Hook |
When called |
Signature |
onStart(ctx) |
App startup |
(ctx: PluginContext) => void | Promise<void> |
onStop() |
App shutdown |
() => void | Promise<void> |
beforeRender(md, route) |
Before Markdown rendering |
(md: string, route: string) => string | Promise<string> |
afterRender(html, route) |
After HTML injection |
(html: string, route: string) => void | Promise<void> |
onRouteChange(route) |
Route change |
(route: string) => void | Promise<void> |
Creating a Plugin
const myPlugin = {
name: 'my-plugin', // required, must be unique
version: '1.0.0', // optional
onStart(ctx) {
console.log('[my-plugin] Started', ctx.config)
},
beforeRender(md, route) {
// Add a banner at the top of every page
return `> 🔖 Route: ${route}\n\n` + md
},
afterRender(html, route) {
console.log('[my-plugin] HTML rendered for', route, '—', html.length, 'bytes')
},
onRouteChange(route) {
console.log('[my-plugin] Navigating to', route)
},
onStop() {
console.log('[my-plugin] Stopped')
},
}
Registering Plugins
Use createPluginManager() to manage your plugins, then pass them to createApp():
import { createApp, createPluginManager } from 'ontowave'
const plugins = createPluginManager()
.use(myPlugin)
.use(anotherPlugin)
const app = createApp({
// ... other dependencies ...
plugins: plugins.getPlugins(),
})
await app.start()
Example Plugins
Logging Plugin
const loggerPlugin = {
name: 'logger',
onRouteChange(route) {
console.log('[logger] Route:', route)
},
afterRender(_html, route) {
console.log('[logger] Render complete:', route)
},
}
Analytics Plugin
const analyticsPlugin = {
name: 'analytics',
onRouteChange(route) {
// Send to analytics service
navigator.sendBeacon('/track', JSON.stringify({ page: route, ts: Date.now() }))
},
}
Markdown Transformation Plugin
const badgePlugin = {
name: 'badge',
beforeRender(md) {
// Replace [[badge:new]] with a colored HTML span
return md.replace(/\[\[badge:([^\]]+)\]\]/g,
(_, label) => `<span class="badge">${label}</span>`)
},
}
Active Navigation Plugin
const activeNavPlugin = {
name: 'active-nav',
onRouteChange(route) {
document.querySelectorAll('nav a').forEach(a => {
a.classList.toggle('active', a.getAttribute('href') === `#${route}`)
})
},
}
API Reference
createPluginManager()
Returns a PluginManager with the following methods:
register(plugin) — registers a plugin (warns on duplicate)
use(plugin) — registers and returns the manager (chainable)
getPlugins() — returns the array of registered plugins
PluginContext Interface
Available in onStart(ctx):
ctx.config — full application configuration (AppConfig)
ctx.navigate(path) — programmatically navigate to a path
Known Limitations
beforeRender hooks run sequentially: registration order matters
afterRender receives the HTML before DOM transforms (Mermaid, Kroki, etc.)
- Each plugin must have a unique
name — duplicates are silently ignored with a console warning