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. |
menus¶
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.).
| 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.