Pravljenje ONLYOFFICE plugin-ova: saveti, trikovi i skrivene zamke

21 January 2026By Natalija Blagojevic

Pravljenje plugin-a za ONLYOFFICE urednike može biti jednostavno, ali razvoj u stvarnom svetu često otkriva neočekivane izazove, od uskih grla u performansama i mrežnih hira do suptilnih razlika između veb i desktop okruženja. Ovaj članak pokriva praktične savete, proverene tehnike i uobičajene zamke na koje ćete verovatno naići kada pravite pouzdane dodatke koji neometano rade u svim uređivačima i scenarijima primene.

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

Bridge i tok rada

UI vašeg plugin-a radi u sopstvenom prozoru i komunicira sa editorom putem message bridge-a. Ovaj bridge najbolje radi sa malim količinama podataka i brzim, fokusiranim izmenama. Razdvajanje UI posla (kao što su preuzimanje podataka ili filtriranje lista) od izmena dokumenta (kao što je umetanje teksta) čini sve bržim, lakšim za debagovanje i predvidljivijim kada više korisnika uređuje istovremeno.

Držite izmene dokumenta kratkim i fokusiranim

Zašto: Komande editora se izvršavaju u jednom prolazu; grupisanje povezanih izmena izbegava treperenje i održava stanje dokumenta doslednim.

Primer (Document Editor, umetanje citata):

// 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);

Savet: Testirajte pozive editor API-ja u playground-u da biste proverili sintaksu i ponašanje pre nego što ih integrišete u plugin.

Ne preuzimajte podatke unutar editor komandi

Zašto: Čekanje na mrežne zahteve unutar komande zamrzava editor.

Primer (anti-pattern vs. ispravno):

    // 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);

Šaljite samo male količine podataka preko bridge-a

Zašto: Bridge je optimizovan za payload-ove nalik JSON-u; veliki stringovi ili ugnježdeni objekti povećavaju latenciju.

Razdvojite UI posao i posao nad dokumentom

Zašto: Preuzimanje, parsiranje i filtriranje pripadaju prozoru vašeg dodatka; samo konačno umetanje se izvršava u editor komandi.

Bezbednost i umrežavanje

Plugin-ovi često preuzimaju sadržaj iz eksternih izvora kao što su RSS feed-ovi ili API-ji. Bez odgovarajućih provera, možete slučajno uneti štetan kod u UI dodatka, naići na cross-origin greške koje blokiraju zahteve ili tiho doživeti neuspeh prilikom mešanja HTTP i HTTPS. Jednostavan plan bezbednosti i umrežavanja sprečava ove glavobolje.

Ključne prakse, sa primerima

Očistite nepouzdan HTML pre nego što ga prikažete

Zašto: Sažeci ili isečci iz feed-ova mogu sadržati HTML koji kvari UI ili uvodi bezbednosne rizike.

Primer:

// 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;

Preferirajte umetanje čistog teksta u dokumente

Obrazloženje: Čist tekst izbegava neočekivano prenošenje formatiranja i održava bridge payload-ove malim; bogato formatiranje rezervišite za namensku, editor-side upotrebu API-ja.

Koristite HTTPS i izbegavajte mixed content

Obrazloženje: Pregledači blokiraju HTTP resurse u bezbednim kontekstima; tihi neuspeh je čest kada endpoint-i nisu HTTPS.

Koristite jednostavan proxy za cross-origin zahteve

Obrazloženje: Mnogi endpoint-i ne dozvoljavaju direktan cross-origin pristup; mali proxy dodaje CORS zaglavlja i normalizuje izlaz.

Primer (Node/Express skica):

 // 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);

Performance, pakovanje i provera pre objave

Plugin-ovi rade dok korisnici aktivno uređuju dokumente, pa je odziv bitan. Dobre prakse performansi, čisto pakovanje i temeljno testiranje pre izdanja održavaju vaš plugin brzim, predvidljivim i lakim za ažuriranje.

Performanse zavise od doslednih navika: debounce pretraga i filtera, virtualizacija dugih lista, prethodno izračunavanje tačnih stringova koji će biti umetnuti kako bi se smanjio trošak po akciji. Prilikom zatvaranja, očistite tajmere, prekinite in-flight zahteve i uklonite listenere kako biste sprečili spora curenja koja se akumuliraju kroz sesije.

const controller = new AbortController();
const timer = setInterval(refresh, 300000);

window.Asc.plugin.button = function () {
  controller.abort();
  clearInterval(timer);
  window.Asc.plugin.executeCommand("close", "");
};

Ključne prakse

  1. Bundle-ujte svoj JavaScript i CSS lokalno umesto oslanjanja na eksterne CDN-ove.
  2. Definišite sopstvene light i dark šeme boja umesto pretpostavke da će editor to obezbediti.
  3. Održavajte identifikator plugin-a (GUID) stabilnim kroz verzije kako bi ažuriranja radila glatko.
  4. Koristite jasne brojeve verzija (1.0.0, 1.1.0, 2.0.0) koji signaliziraju šta se promenilo.
  5. Uključite sve potrebne ikonice i metapodatke za Plugin Manager i Marketplace.
  6. Testirajte sa URL-ovima nalik produkciji kako biste uhvatili polomljene putanje slika ili skripti.

Pre objave, uradite kompaktan ali strog prolaz kroz podržane editore (Document, Spreadsheet, Presentation), okruženja (web i desktop), teme (light i dark), kolaboraciju (istovremena umetanja), mrežne uslove (offline, sporo, proxy down), veličine skupova podataka (malo i veoma veliko) i strožiji CSP bez inline skripti ili stilova, kako bi ponašanje ostalo dosledno kada stvarni korisnici i stvarne mreže stave plugin na test.

Zaključak

Pouzdani plugin-ovi nastaju iz jednostavnih navika: prvo pripremite podatke, promene u dokumentu napravite u jednom fokusiranom koraku, sanitizujte eksterni sadržaj, usmerite mrežne pozive kroz mali proxy i sve spakujte lokalno kako bi radilo isto svuda. Testirajte kroz editore, okruženja, teme i mrežne uslove pre objave, kako bi se vaš plugin ponašao predvidljivo kada ga stvarni korisnici i stvarne mreže koriste.

Create your free ONLYOFFICE account

View, edit and collaborate on docs, sheets, slides, forms, and PDF files online.