Como desenvolver um plugin DocSpace – tutorial completo passo a passo

21 maio 2025Por Klaibson

Em um mundo onde velocidade e colaboração são essenciais, as ferramentas de produtividade precisam acompanhar esse ritmo. Os plugins do DocSpace oferecem uma maneira moderna de aprimorar a forma como os usuários gerenciam e interagem com documentos. Neste guia, mostraremos como criar seu próprio plugin do DocSpace usando exemplos reais de nossos exemplos oficiais de plugins.

Como desenvolver um plugin DocSpace – tutorial completo passo a passo

Sobre o ONLYOFFICE DocSpace Plugins SDK

ONLYOFFICE DocSpace Plugins SDK é um pacote npm baseado em mecanismos TypeScript que fornece interfaces que permitem criar seus próprios plugins e incorporá-los ao portal DocSpace. O ciclo de vida de desenvolvimento do plugin inclui planejamento, desenvolvimento, testes e uso.

Para ilustrar como usar nosso SDK de plugins, criamos um repositório com o plugin samples. Vamos mergulhar em todo o processo de desenvolvimento de plugins com base em nossos exemplos de plugins.

Planejamento

Defina a finalidade do plugin, pense onde você irá acessá-lo e quais serviços de terceiros você precisa conectar.

Etapa 1. Instale todos os pacotes e programas necessários

Instale @onlyoffice/docspace-plugin-sdk pacote npm globalmente, use o seguinte comando:

 npm i -g @onlyoffice/docspace-plugin-sdk

Etapa 2. Projete a maneira como seu plugin funcionará

Escolha o serviço que permite adicionar a funcionalidade necessária ao seu DocSpace.

Por exemplo, em nossos exemplos de plugins, usamos:

  • AssemblyAI para converter fala de arquivos de áudio e vídeo em texto;
  • ConvertAPI para converter documentos, planilhas, apresentações e formulários em PDF;
  • Draw.io  para criar, editar e inserir diagramas com aparência profissional.

Observação! Certifique-se de que a documentação do serviço esteja disponível, verifique sua licença, a disponibilidade dos métodos de API, etc. Para alguns serviços, o usuário precisa obter uma chave de API para começar a usar o plugin.

Pense em onde implementar o plugin, qual será sua estrutura, como o usuário interagirá com seus componentes, etc. Faça uma lista dos tipos e itens de plugin necessários com base nessas informações. Para mais informações, leia o Plugin types e Plugin items seções da documentação do Plugins SDK.

Por exemplo, para o plugin de conversão de fala em texto, usamos as seguintes interfaces de plugin:

  • IPlugin. Obrigatório para cada plugin. Contém o plugin PluginStatus variável, usada para incorporar o plugin no DocSpace.
  • ApiPlugin. Obrigatório porque implementamos um serviço de terceiros.
  • ISettingsPlugin e ISettings. Usado para adicionar um bloco de configurações para a configuração do plugin. Os usuários podem acessar este bloco em Configurações -> Integração -> Plugins para ajustar os parâmetros do plugin.
  • IContextMenuPlugin e IContextMenuItem. Usado para implementar uma ação de menu de contexto. No plugin de conversão de fala em texto, estará disponível para arquivos de vídeo e áudio, permitindo que os usuários convertam conteúdo em texto.

A lista de interfaces pode ser maior. Por exemplo, no plugin draw\.io:

  • IMainButtonPlugin e IMainButtonItem. Usado para implementar a ação do botão principal. No plugin draw\.io, usamos o botão Ação -> Mais elementos de menu na seção Meus documentos ou na sala selecionada para criar diagramas draw\.io.
  • IFilePlugin e IFileItem. Usado para interagir com os tipos de arquivo especificados. Neste caso, com os arquivos .drawio.

Crie a estrutura do plugin. Todos os arquivos necessários estão descritos aqui. Todo o resto pode ser organizado como você preferir. Por exemplo, no plugin draw\.io, colocamos o código para cada tipo de plugin em pastas separadas, enquanto no plugin de conversão de voz em texto, esse código é colocado na pasta src.

Como desenvolver um plugin DocSpace – tutorial completo passo a passo

Escolha um nome para seu plugin e escreva uma descrição para ele.

Em desenvolvimento

Agora que todo o trabalho de preparação foi concluído, você pode começar a desenvolver seu plugin.

Etapa 1. Crie um modelo de plugin

Crie um modelo de plugin e configure suas configurações, que serão exibidas nas configurações do plugin DocSpace:

Para criar um modelo de plugin, abra o terminal e execute o seguinte comando npx:

 npx create-docspace-plugin

Se o comando npm não estiver disponível, instale o @onlyoffice/docspace-plugin-sdk pacote npm globalmente usando o seguinte comando:

npm i -g @onlyoffice/docspace-plugin-sdk

Configure o plugin no terminal, especificando as configurações na caixa de diálogo. Todas as configurações são descritas aqui.

Para o plugin de conversão de fala em texto, você pode usar os seguintes valores:

Como desenvolver um plugin DocSpace – tutorial completo passo a passo

Você pode alterar todos os parâmetros especificados posteriormente no package.json file.

Você também pode criar um plugin em qualquer projeto adicionando o @onlyoffice/docspace-plugin-sdk pacote npm como uma dependência e especificando todos os campos necessários no arquivo package.json.

Etapa 2. Configurar o ponto de entrada do plugin

O index.ts O ponto de entrada do plugin será criado automaticamente na pasta src durante a etapa de criação do modelo. Este arquivo é necessário.

Este arquivo contém todos os métodos básicos dos tipos de plugins que você selecionou na etapa anterior. Você pode alterá-lo a qualquer momento.

Se você mesmo criar um plugin, sem um modelo, para o ponto de entrada do plugin, poderá usar o código dos nossos exemplos de plugins prontos. Funcionará perfeitamente.

Etapa 3. Adicionar ícones de plugin

Cria a pasta assets na pasta raiz do plugin e adicione todos os ícones do plugin. O número de ícones e seus tamanhos dependerão dos tipos de plugin que você implementar. Para o plugin de conversão de voz em texto, precisamos dos seguintes ícones:

  • O tipo de plugin padrão requer uma imagem logo . É igual ao parâmetro logo do arquivo package.json. O logotipo será exibido nas configurações do plugin DocSpace. O tamanho do ícone necessário é 48×48 px. Caso contrário, ele será compactado para este tamanho.
    (no title)
  • O plugin do menu de contexto usa um icon no botão Converter em texto. O tamanho do ícone necessário é 16×16 px. Caso contrário, ele será compactado para este tamanho.

Como desenvolver um plugin DocSpace – tutorial completo passo a passo

Este ícone também pode ser usado para o ícone do botão principal. Por exemplo, no plugin draw\.io, o mesmo ícone é usado para o menu de contexto e do botão principal.

Como desenvolver um plugin DocSpace – tutorial completo passo a passo

O plugin draw\.io também usa o ícone de arquivo específico próximo aos arquivos .drawio, que são criados com o tipo de plugin de arquivo. O tamanho de ícone preferido para o formato de tabela é 32×32 px.

Como desenvolver um plugin DocSpace – tutorial completo passo a passo

Etapa 4. Configurar os elementos da interface do plugin

Por exemplo, o plugin draw\.io contém dois elementos principais de interface do usuário: a janela modal e o editor de diagramas. Crie os arquivos para configurar cada elemento. Para sua conveniência, você pode colocar esses arquivos em uma pasta separada do DrawIO.

No arquivo Dialog.ts , configurar as configurações da janela modal. Especifique o IFrame componente de interface do usuário usado para incorporar o site draw\.io em uma janela modal:

  export const frameProps: IFrame = {
    width: "100%",
    height: "100%",
    name: "test-drawio",
    src: "",
  }

Criar o container IBox para adicionar o iframe a ele:

 const body: IBox = {
    widthProp: "100%",
    heightProp: "100%",


    children: [
      {
        component: Components.iFrame,
        props: frameProps,
      },
    ],
  }

Configure as propriedades da modal window :

 export const drawIoModalDialogProps: IModalDialog = {
    dialogHeader: "",
    dialogBody: body,
    displayType: ModalDisplayType.modal,
    fullScreen: true,
    onClose: () => {
      const message: IMessage = {
        actions: [Actions.closeModal],
      }
      return message
    },
    onLoad: async () => {
      return {
        newDialogHeader: drawIoModalDialogProps.dialogHeader || "",
        newDialogBody: drawIoModalDialogProps.dialogBody,
      }
    },
    autoMaxHeight: true,
    autoMaxWidth: true,

No arquivo Editor.ts , Configure o editor de diagramas. Crie a função DiagramEditor com os seguintes parâmetros:

Parâmeter Tipo Exemplo Descrição
ui string “default” Define o tema da interface do usuário do editor.
dark string “auto” Define o tema escuro do editor.
off boolean false Especifica se o modo offline está ativo ou não.
lib boolean false Especifica se as bibliotecas estão habilitadas ou não.
lang string “auto” Define o idioma do editor.
url string `https://embed.diagrams.net` Define a URL para o editor.
showSaveButton boolean true Especifica se o botão **Salvar** será exibido no editor.

Em seguida, especifique métodos para trabalhar com diagramas:

Método Descrição
startEditing Inicia o editor com os dados fornecidos.
getData Retorna os dados do diagrama.
getTitle Retorna o título do diagrama.
getFormat Retorna o formato do diagrama.
getFrameId Retorna o ID do quadro do editor.
getFrameUrl Retorna a URL para o iframe.
handleMessage Manipula a mensagem fornecida.
initializeEditor Envia a mensagem *load* para o editor.
save Salva os dados fornecidos.

O código completo do *DiagramEditor* pode ser encontrado aqui

Etapa 5. Criar tipos de plugin

Agora que o plugin padrão está pronto, você pode começar a codificar outros tipos de plugin.

Cada tipo de plugin possui itens de plugin específicos. Defina o item do menu de contexto que será exibido quando você clicar com o botão direito em arquivos de áudio ou vídeo:

export const contextMenuItem:
 
IContextMenuItem = {
  key: "speech-to-text-context-menu-item",
  label: "Convert to text",
  icon: "speech-to-text-16.png",
  onClick: assemblyAI.speechToText,
  fileType: [FilesType.video],
  withActiveItem: true,
}

Como desenvolver um plugin DocSpace – tutorial completo passo a passo

Você pode adicionar mais tipos de plugins. Por exemplo, o plugin draw\.io pode ser acessado a partir do menu principal do botão, então precisamos especificar o item do botão principal:

const mainButtonItem: IMainButtonItem = {
  key: "draw-io-main-button-item",
  label: "Draw.io",
  icon: "drawio.png",
  onClick: (id: number) => {
    drawIo.setCurrentFolderId(id)


    const message: IMessage = {
      actions: [Actions.showCreateDialogModal],
      createDialogProps: {
        title: "Create diagram",
        startValue: "New diagram",
        visible: true,
        isCreateDialog: true,
        extension: ".drawio",
        onSave: async (e: any, value: string) => {
          await drawIo.createNewFile(value)
        },
        onCancel: (e: any) => {
          drawIo.setCurrentFolderId(null)
        },
        onClose: (e: any) => {
          drawIo.setCurrentFolderId(null)
        },
      },
    }
    return message
  },
  // items: [createItem],
}

Quando o item do botão principal é clicado, a janela modal aparece onde você pode digitar o nome do diagrama e abrir um arquivo .drawio vazio.

Como desenvolver um plugin DocSpace – tutorial completo passo a passo

Para o plugin draw\.io, você também precisa configurar o tipo de plugin de arquivo que funciona quando o usuário abre o arquivo .drawio específico:

Defina o item do arquivo que é representado como um arquivo com a extensão específica (.drawio) e ícone:

 export const drawIoItem: IFileItem = {
     extension: ".drawio",
     fileTypeName: "Diagram",
     fileRowIcon: "drawio-32.svg",
     fileTileIcon: "drawio-32.svg",
     devices: [Devices.desktop],
     onClick,
   }

Defina o evento onClick que executará o método editDiagram sempre que o arquivo .drawio for aberto:

  const onClick = async (item: File) => {
     return await drawIo.editDiagram(item.id)
   }

Como desenvolver um plugin DocSpace – tutorial completo passo a passo

Etapa 6. Crie o tipo de plugin de configurações

Configure o tipo de plugin de configurações para fornecer aos usuários as configurações de administrador.

Crie um contêiner onde as configurações do plugin serão armazenadas:

 const descriptionText: TextGroup = {
     component: Components.text,
     props: {
       text: "To generate API token visit https://www.assemblyai.com",
       color: "#A3A9AE",
       fontSize: "12px",
       fontWeight: 400,
       lineHeight: "16px",
     },
   }
   
   const descGroup: BoxGroup = {
     component: Components.box,
     props: {children: [descriptionText]},
   }
   
   const parentBox: IBox = {
     displayProp: "flex",
     flexDirection: "column",
     // marginProp: "16px 0 0 0",
     children: [tokenGroup, descGroup],
   }

Na descrição das configurações, indique que é necessário gerar um token de API para poder trabalhar com o plugin.

Configure as configurações de administrador com o objeto ISettings:

const adminSettings: ISettings = {
     settings: parentBox,
     saveButton: userButtonComponent,
     onLoad: async () => {
       assemblyAI.fetchAPIToken()
   
       tokenInput.value = assemblyAI.apiToken
   
       if (!assemblyAI.apiToken) {
         return {
           settings: parentBox,
         }
       }


       plugin.setAdminPluginSettings(adminSettings)
   
       return {settings: parentBox}
     }

Especifique o evento onLoad, que define quais configurações do plugin serão exibidas quando o bloco de configurações for carregado.

Cada item de configuração é definido em arquivos separados. (botões, token).

Como desenvolver um plugin DocSpace – tutorial completo passo a passo

Etapa 7. Crie o arquivo de código do plugin principal

Crie um arquivo na pasta src com o código principal do plugin. Este arquivo é necessário. Consulte a documentação de um serviço de terceiros para escrever este código.

Vamos ver como o arquivo AssemblyAI.ts é organizado em detalhes:

Defina a classe AssemblyAI com todas as variáveis ​​e métodos necessários:

  • Variáveis ​​e sua descrição:

apiURL

Define a URL da API.

apiURL = ""

currentFileId

Define o ID do arquivo atual.

const currentFileId: numbernull | number = null

apiToken

Define o token da API.

 apiToken = ""
  • Métodos e sua descrição

createAPIUrl

Cria a URL da API.

 createAPIUrl = () => {
     const api = plugin.getAPI()


     this.apiURL = api.origin.replace(/\/+$/, "")


     const params = [api.proxy, api.prefix]


     if (this.apiURL) {
       for (const part of params) {
         if (!part) {
           continue
         }
         const newPart = part.trim().replace(/^\/+/, "")
         if (newPart) {
           if (this.apiURL.length !== 0 && this.apiURL[this.apiURL.length - 1] === "/") {
             this.apiURL += newPart
           } else {
             this.apiURL += `/${newPart}`
           }
         }
       }
     }
   }

setAPIUrl

Define a URL da API.

 setAPIUrl = (url: string) => {
     this.apiURL = url
   }

getAPIUrl

Retorna a URL da API.

 getAPIUrl = () => {
     return this.apiURL
   }

setAPIToken

Define o token da API.

   setAPIToken = (apiToken: string) => {
     this.apiToken = apiToken
   }

getAPIToken

Retorna o token da API.

   getAPIToken = () => {
     return this.apiToken
   }

fetchAPIToken

Busca o token da API.

   fetchAPIToken = async () => {
     const apiToken = localStorage.getItem("speech-to-text-api-token")
  
     if (!apiToken) {
       return
     }


     this.setAPIToken(apiToken)
     plugin.updateStatus(PluginStatus.active)
   }

saveAPIToken

Salva o token da API.

   saveAPIToken = (apiToken: string) => {
     localStorage.setItem("speech-to-text-api-token", apiToken)
  
     let status
     if (apiToken) {
       status = PluginStatus.active
     } else {
       status = PluginStatus.hide
     }
     plugin.updateStatus(status)
   }

setCurrentFileId

Define o ID para o arquivo atual.

 setCurrentFileId = (id: number | null) => {
     this.currentFileId = id
   }

uploadFile

Carrega um arquivo que será transcrito.

uploadFile = async (apiToken: string, path: string, data: Blob) => {
     console.log(`Uploading file: ${path}`)
  
     const url = "https://api.assemblyai.com/v2/upload"
  
     try {
       const response = await fetch(url, {
         method: "POST",
         body: data,
         headers: {
           "Content-Type": "application/octet-stream",
           "Authorization": apiToken,
         },
       })
  
       if (response.status === 200) {
         const responseData = await response.json()
         return responseData["upload_url"]
       }
       console.error(`Error: ${response.status} - ${response.statusText}`)
       return null
     } catch (error) {
       console.error(`Error: ${error}`)
       return null
     }
   }

transcribeAudio

Transcreve o arquivo de áudio.

transcribeAudio = async (apiToken: string, audioUrl: string) => {
     console.log("Transcribing audio... This might take a moment.")
  
     const headers = {
       "authorization": apiToken,
       "content-type": "application/json",
     }
     const response = await fetch("https://api.assemblyai.com/v2/transcript", {
       method: "POST",
       body: JSON.stringify({audioUrl}),
       headers,
     })
  
     const responseData = await response.json()
     const transcriptId = responseData.id
  
     const pollingEndpoint = `https://api.assemblyai.com/v2/transcript/${transcriptId}`
  
     while (true) {
       const pollingResponse = await fetch(pollingEndpoint, {headers})
       const transcriptionResult = await pollingResponse.json()
  
       if (transcriptionResult.status === "completed") {
         return transcriptionResult
       } else if (transcriptionResult.status === "error") {
         throw new Error(`Transcription failed: ${transcriptionResult.error}`)
       } else {
         await new Promise((resolve) => {
           setTimeout(resolve, 3000)
         })
       }
     }
   }

speechToText

Implementa a funcionalidade do plugin.

speechToText = async (id: number) => {
     if (!this.apiToken) {
       return
     }


     this.setCurrentFileId(null)
  
     if (!this.apiURL) {
       this.createAPIUrl()
     }


     const response = await fetch(`${this.apiURL}/files/file/${id}`)
     const data = await response.json()
     const {viewUrl, title, folderId, fileExst} = data.response
  
     const file = await fetch(viewUrl)
  
     const fileBlob = await file.blob()
  
     const uploadUrl = await this.uploadFile(this.apiToken, viewUrl, fileBlob)
  
     const transcript = await this.transcribeAudio(this.apiToken, uploadUrl)
  
     const blob = new Blob([transcript.text], {
       type: "text/plain;charset=UTF-8",
     })
  
     const newFile = new File([blob], "blob", {
       type: "",
       lastModified: Date.now(),
     })
  
     const formData = new FormData()
     formData.append("file", newFile)
  
     const newTitle = `${title.replaceAll(fileExst, "")} text`
  
     try {
       const sessionRes = await fetch(
         `${this.apiURL}/files/${folderId}/upload/create_session`,
         {
           method: "POST",
           headers: {
             "Content-Type": "application/json;charset=utf-8",
           },
           body: JSON.stringify({
             createOn: new Date(),
             fileName: `${newTitle}.txt`,
             fileSize: newFile.size,
             relativePath: "",
           }),
         },
       )
       const response = await sessionRes.json()
       const sessionData = response.response.data
  
       const data = await fetch(`${sessionData.location}`, {
         method: "POST",
         body: formData,
       })


       const jsonData = await data.json()
       const {id: fileId} = jsonData.data
  
       return fileId
     } catch (e) {
       console.log(e)
     }


     return {
       actions: [Actions.showToast],
       toastProps: [{type: ToastType.success, title: ""}],
     } as IMessage
   }

Declare a instância da classe AssemblyAI:

const assemblyAI = new AssemblyAI()

Exporte a instância do plugin criada:

export default assemblyAI

Teste

Para verificar a funcionalidade do plugin e corrigir possíveis bugs, teste o plugin:

  • Crie o plugin preparado seguindo as instruções aqui

A pasta dist será criada na pasta raiz do plugin e o arquivo do plugin será armazenado nela. Este arquivo é o plugin completo que pode ser carregado no portal DocSpace.

  •  Upload seu plugin para o portal DocSpace e teste completamente sua aparência e funcionalidade.

Observação! Observe que você só pode enviar seus próprios plugins na versão DocSpace do servidor.

Caso ocorra algum erro, corrija o código-fonte do seu plugin e repita o procedimento de compilação e teste.

Agora que seu plugin foi testado e funciona corretamente, você pode adicioná-lo à versão DocSpace do servidor e começar a usá-lo.

O plugin DocSpace oferece uma abordagem poderosa e intuitiva para gerenciamento e colaboração de documentos. Ao se integrar às plataformas preferidas dos usuários, ele remove obstáculos comuns e melhora a produtividade em diferentes fluxos de trabalho. Se você tiver alguma dúvida sobre os plugins DocSpace, não hesite em perguntar aos nossos desenvolvedores no fórum ONLYOFFICE (é necessário registro). Você também pode solicitar um recurso ou relatar um bug postando um problema no GitHub ou compartilhe seus plugins do DocSpace conosco e com outros usuários. Boa sorte em seus empreendimentos exploratórios!

Crie sua conta gratuita no ONLYOFFICE

Visualize, edite e colabore em documentos, planilhas, slides, formulários e arquivos PDF online.