Saltar a contenido

Referencia de plugin.json

Todo plugin de Python declara su identidad, su punto de entrada y su colocación en la barra de menús en un archivo plugin.json situado junto a su main.py. Es el mismo esquema que usa el lado de C++; solo los campos entry y module son específicos de Python.

Ejemplo

{
  "id":          "org.example.wordcount",
  "name":        "Word Count",
  "version":     "1.0.0",
  "vendor":      "Example, Inc.",
  "description": "Counts words and characters in the active document.",
  "apiVersion":  1,
  "entry":       "python",
  "module":      "main",
  "pyRequires":  [],
  "order":       900,
  "menus": [
    { "title": "Plugins", "barPriority": 570, "itemPriority": 100 }
  ]
}

Campos

Obligatorios

Campo Tipo Notas
id cadena Identificador único en DNS inverso. Se usa en todas partes: activar/desactivar, líneas de registro, ajustes por plugin. No debe cambiar entre versiones.
apiVersion entero Debe ser igual al MTE_PLUGIN_API_VERSION del anfitrión. Actualmente 1. Una discrepancia aparece en la página de Plugins y el plugin se lista, pero no se carga.
entry cadena Debe ser "python" para encaminarlo por el backend de Python. "native" u omitido lo encamina por el cargador de Qt.
module cadena Nombre del módulo de Python que contiene register(ctx). Si es "main", el trabajador busca main.py dentro de la carpeta del plugin. Los nombres de paquete con puntos ("src.main") son una extensión futura: la fase 1 solo admite nombres planos.

Recomendados

Campo Tipo Notas
name cadena Nombre legible que se muestra en la página de Plugins.
version cadena Versionado semántico; por lo demás, libre.
vendor cadena Autor u organización. Se muestra en la página de Plugins.
description cadena Una o dos líneas. Se muestra en la página de Plugins.

Opcionales

Campo Tipo Notas
order entero Orden de carga entre plugins; menor se carga antes. 1000 de forma predeterminada. Los empates se resuelven por id. requires tiene prioridad sobre él.
requires matriz de cadenas Identificadores de los plugins sin los que este plugin no puede funcionar (nativos o Python por igual), p. ej. ["org.mte.lsp"]; no son paquetes pip, esos van en pyRequires. Se inician antes que este plugin diga lo que diga order; si alguno falta, está desactivado, bloqueado por la licencia o no se cargó, este plugin no se inicia en absoluto y Preferencias → Complementos indica cuál necesita y por qué. Mismo significado que en un plugin nativo.
apiMinorVersion entero La versión menor mínima de la API del host que necesita este plugin (0 de forma predeterminada). Un plugin Python no tiene un info() compilado, así que esta es su única declaración: indica la versión menor de la llamada más reciente que uses. Un host más antiguo muestra el plugin como «Necesita una versión más reciente de OctoEdit» y no lo inicia.
menus matriz de objetos Ver más abajo.
pyRequires matriz de cadenas Cadenas de requisitos de pip (p. ej. ["requests>=2.31"]). En el primer arranque del plugin, el editor aprovisiona un entorno virtual por plugin, instala estos paquetes con pip dentro de él y ejecuta el trabajador del plugin bajo ese entorno (consulta Empaquetado). Las entradas que no son cadenas y las vacías se omiten.
permissions matriz de cadenas Declaraciones gruesas de capacidades (p. ej. ["network"]), que se muestran en modo de solo lectura en la columna Permisos de Preferencias → Complementos, para que los usuarios vean qué dice hacer un plugin. Solo declaración: todavía no se impone.
thirdParty matriz de objetos Componentes de terceros que incluye el plugin, para su atribución en el diálogo Acerca de. Cada entrada: name (obligatorio), license, url, file. Distribuye el texto de licencia nombrado por file junto al plugin, bajo Plugins/Licenses/<id>/. Ver más abajo.

Cada entrada declara un menú de primer nivel al que contribuye el plugin y fija su posición. Repite un objeto por cada menú de primer nivel que toques (Tools, Plugins, Help, etc.).

"menus": [
  { "title": "Plugins", "barPriority": 570, "itemPriority": 100 }
]
Campo Tipo Notas
title cadena, obligatorio La etiqueta del menú de primer nivel bajo el que vive el elemento (Plugins, Tools, …). Debe coincidir con el segmento más a la izquierda de las rutas que pasas a ctx.menus.add_item().
barPriority entero, opcional Rango de izquierda a derecha en la barra de menús. Menor = más a la izquierda. Los menús del núcleo tienen prioridades fijas separadas de 100 en 100 (Archivo 100, Edición 200, …, Ventana 600); 570 coloca tu submenú cerca de la posición de Plugins. Se repite entre los plugins que apuntan al mismo menú de primer nivel; que gane el último no importa, porque es idempotente.
itemPriority entero, opcional Rango vertical de todo el bloque de tu plugin dentro del menú hoja. 1000 de forma predeterminada. Menor = más arriba.

Aquí NO se listan los elementos individuales: esos los añade ctx.menus.add_item() en tiempo de ejecución. menus solo trata de la colocación en la barra de menús.

thirdParty

Declara cualquier componente de terceros que incluya tu plugin para que el diálogo Acerca de pueda atribuirlo. Cada entrada:

"thirdParty": [
  { "name": "SomeLib", "license": "MIT",
    "url": "https://example.com/", "file": "SomeLib-LICENSE.txt" }
]
Campo Tipo Notas
name cadena, obligatorio El componente. Las entradas sin un nombre no vacío se descartan.
license cadena, opcional Etiqueta al estilo SPDX, p. ej. MIT, LGPL-3.0.
url cadena, opcional Página del proyecto o de inicio.
file cadena, opcional Nombre base del texto de licencia que distribuyes, que se resuelve en Plugins/Licenses/<your-plugin-id>/<file>.

Las licencias son responsabilidad tuya: distribúyelas con el paquete de tu plugin, bajo Plugins/Licenses/<id>/. El editor lista los componentes y remite a los usuarios a esa carpeta; no guarda en su propia carpeta Licenses/ los textos de terceros de tu plugin.

Sondeo estático

En el momento de la detección —y de nuevo cuando se instala un paquete .mteplugin— el anfitrión lee module, abre <pluginDir>/<module>.py y confirma que contiene un def register(...) de nivel superior; no se ejecuta ningún código. El instalador rechaza con un diálogo de error un paquete que no lo cumpla; la detección omite el plugin en silencio, con una línea de error en el registro:

PythonPluginBackend: skipping 'org.example.wordcount': module
'.../main.py' does not declare a top-level `def register(...)`.

Mantén register en la columna 0 de una línea que empiece por def register(.

Orden de carga y colocación en la barra de menús

Si tu plugin contribuye a Plugins con barPriority: 570, el menú aparece en el rango 570 de la barra de menús. Dos plugins con valores de barPriority distintos para el mismo título compiten: gana el que se haya cargado en último lugar, pero como los dos suelen declarar el mismo rango para un menú dado, da igual. Consulta PLUGIN_ARCHITECTURE.md §13 para el modelo de ordenación completo.

Qué NO corresponde aquí

El anfitrión analiza los campos documentados arriba e ignora todo lo demás: no te inventes campos; una clave desconocida es peso muerto en silencio.