Creare plugin ONLYOFFICE: idee, consigli, insidie nascoste

21 gennaio 2026Da Alice

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.

Сreating ONLYOFFICE plugins: tips, tricks, and hidden pitfalls

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

  1. Includi JavaScript e CSS in locale invece di affidarti a CDN esterni.
  2. Definisci schemi di colori chiaro e scuro invece di dare per scontato che li fornisca l’editor.
  3. Mantieni stabile l’identificatore del plugin (GUID) tra le versioni, così gli aggiornamenti funzionano senza problemi.
  4. Usa numeri di versione chiari (1.0.0, 1.1.0, 2.0.0) che indichino cosa è cambiato.
  5. Includi tutte le icone e i metadati richiesti per il Plugin Manager e il Marketplace.
  6. 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.