Creare plugin ONLYOFFICE: idee, consigli, insidie nascoste
Creare plugin per gli editor ONLYOFFICE può sembrare semplice, ma nello sviluppo reale emergono spesso sfide inaspettate: intoppi nelle prestazioni, particolarità di rete e sottili differenze tra ambienti web e desktop. Questo articolo raccoglie consigli pratici, tecniche collaudate e problemi comuni che probabilmente incontrerai quando crei plugin affidabili, in grado di funzionare in modo fluido tra diversi editor e scenari di distribuzione.

Bridge e workflow
L’interfaccia del tuo plugin viene eseguita in una finestra separata e comunica con l’editor tramite un message bridge. Questo bridge funziona al meglio con piccole quantità di dati e modifiche rapide e mirate. Tenere separato il lavoro sull’interfaccia (come il recupero dei dati o il filtraggio delle liste) dalle modifiche al documento (come l’inserimento di testo) rende tutto più veloce, più facile da debuggare e più prevedibile quando più utenti modificano contemporaneamente.
Mantieni le modifiche al documento brevi e focalizzate
Perché: i comandi dell’editor vengono eseguiti in un’unica operazione; raggruppare le modifiche correlate evita sfarfallii e mantiene lo stato del documento coerente.
Esempio (Document Editor, inserimento di una citazione):
// UI side: prepare compact data
const citation = `${title} - ${source}${date ? ', ' + date : ''}`;
Asc.scope.citation = citation;
// Editor side: run atomically
window.Asc.plugin.callCommand(function () {
var doc = Api.GetDocument();
var p = Api.CreateParagraph();
p.AddText(Asc.scope.citation);
doc.InsertContent([p]);
}, true);
Consiglio: testa le chiamate all’API dell’editor nel playground per verificare sintassi e comportamento prima di integrarle nel plugin.
Non recuperare dati all’interno dei comandi dell’editor
Perché: attendere richieste di rete all’interno di un comando blocca l’editor.
Esempio (anti-pattern vs. soluzione corretta):
// Anti-pattern: async in callCommand (don't do this)
window.Asc.plugin.callCommand(async function () {
const res = await fetch(url);
const text = await res.text();
Api.GetDocument().InsertContent([Api.CreateParagraph().AddText(text)]);
}, true);
// Correct: fetch in the plugin window, then pass small data
const res = await fetch(url);
const text = await res.text().then(t => t.slice(0, 200)); // trim
Asc.scope.snippet = text;
window.Asc.plugin.callCommand(function () {
var p = Api.CreateParagraph();
p.AddText(Asc.scope.snippet);
Api.GetDocument().InsertContent([p]);
}, true);
Invia solo piccole quantità di dati attraverso il bridge
Perché: il bridge è ottimizzato per payload simili a JSON; stringhe molto grandi o oggetti annidati aumentano la latenza.
Tieni separato il lavoro sull’interfaccia da quello sul documento
Perché: recupero, parsing e filtraggio appartengono alla finestra del plugin; solo l’inserimento finale deve avvenire tramite il comando dell’editor.
Sicurezza e networking
I plugin spesso recuperano contenuti da fonti esterne come feed RSS o API. Senza i controlli adeguati, si rischia di introdurre codice dannoso nell’interfaccia del plugin, incorrere in errori cross-origin che bloccano le richieste o avere fallimenti silenziosi mescolando HTTP e HTTPS. Un piano semplice per sicurezza e networking evita questi problemi.
Pratiche chiave, con esempi
Pulisci l’HTML non attendibile prima di mostrarlo
Perché: riassunti o snippet dei feed possono contenere HTML che rompe l’interfaccia o introduce rischi di sicurezza.
Esempio:
// Quick plain-text extraction
function toPlainText(html) {
const tmp = document.createElement("div");
tmp.innerHTML = html;
return tmp. textContent || "";
}
const safeText = toPlainText(untrustedHtml);
// If rendering controlled HTML, use a sanitizer (e. g., DOMPurify)
// const safeHtml = DOMPurify.sanitize(untrustedHtml);
// container.innerHTML = safeHtml;
Prediligi l’inserimento testo semplice nei documenti
Motivazione: il testo semplice evita trascinamenti di formattazione indesiderati e mantiene piccoli i payload del bridge; riserva la formattazione avanzata a un uso consapevole delle API lato editor.
Usa HTTPS ed evita contenuti misti
Motivazione: i browser bloccano le risorse HTTP in contesti sicuri; i fallimenti silenziosi sono comuni quando gli endpoint non sono HTTPS.
Usa un proxy semplice per le richieste cross-origin
Motivazione: molti endpoint non consentono accesso cross-origin diretto; un piccolo proxy aggiunge header CORS e normalizza l’output.
Esempio (bozza Node/Express):
// Minimal CORS/normalize proxy (server-side)
import express from "express";
import fetch from "node-fetch";
const app = express();
app.get("/feed", async (req, res) => {
try {
const url = new URL(req.query.src);
const r = await fetch(url.toString(), { timeout: 8000 });
const text = await r.text();
// Convert to normalized JSON shape server-side as needed
res.set("Access-Control-Allow-Origin", "*");
res.json({ items: normalizeToCommonShape(text) });
} catch (e) {
res.set("Access-Control-Allow-Origin", "*");
res.status(502).json({ error: "Upstream fetch failed" });
}
});
app.listen(3000);
Prestazioni, packaging e fase pre-rilascio
I plugin vengono eseguiti mentre gli utenti modificano attivamente i documenti, quindi la reattività è fondamentale. Buone abitudini sulle prestazioni, un packaging pulito e test approfonditi prima del rilascio mantengono il plugin veloce, prevedibile e facile da aggiornare.
Le prestazioni dipendono da abitudini costanti: applica debounce a ricerche e filtri, virtualizza le liste lunghe, calcola in anticipo le stringhe esatte da inserire per ridurre il costo di ogni azione. Alla chiusura, cancella i timer, interrompi le richieste in corso e rimuovi i listener per evitare piccole perdite che si accumulano tra le sessioni.
const controller = new AbortController();
const timer = setInterval(refresh, 300000);
window.Asc.plugin.button = function () {
controller.abort();
clearInterval(timer);
window.Asc.plugin.executeCommand("close", "");
};
Pratiche chiave
- Includi JavaScript e CSS in locale invece di affidarti a CDN esterni.
- Definisci schemi di colori chiaro e scuro invece di dare per scontato che li fornisca l’editor.
- Mantieni stabile l’identificatore del plugin (GUID) tra le versioni, così gli aggiornamenti funzionano senza problemi.
- Usa numeri di versione chiari (1.0.0, 1.1.0, 2.0.0) che indichino cosa è cambiato.
- Includi tutte le icone e i metadati richiesti per il Plugin Manager e il Marketplace.
- Testa con URL simili a quelli di produzione per individuare percorsi errati di immagini o script.
Prima del rilascio, esegui una verifica compatta ma rigorosa su editor supportati (Documento, Foglio di calcolo, Presentazione), ambienti (web e desktop), temi (chiaro e scuro), collaborazione (inserimenti simultanei), condizioni di rete (offline, lenta, proxy non disponibile), dimensioni dei dataset (molto piccoli e molto grandi) e con una CSP più restrittiva senza script o stili inline, in modo che il comportamento resti coerente quando utenti reali e reti reali mettono il plugin alla prova.
Conclusione
I plugin solidi nascono da abitudini semplici: prepara prima i dati, applica le modifiche al documento in un unico passaggio mirato, sanitizza i contenuti esterni, instrada le chiamate di rete attraverso un piccolo proxy e pacchettizza tutto in locale affinché funzioni allo stesso modo ovunque. Testa su editor, ambienti, temi e condizioni di rete prima del rilascio, così il tuo plugin si comporterà in modo prevedibile quando utenti reali e reti reali lo utilizzeranno.
Crea il tuo account ONLYOFFICE gratuito
Visualizza, modifica e collabora su documenti, fogli, diapositive, moduli e file PDF online.


