Aller au contenu

Référence plugin.json

Chaque plugin Python déclare son identité, son point d'entrée et son placement dans la barre de menus dans un fichier plugin.json situé à côté de son main.py. C'est le même schéma que côté C++ ; seuls les champs entry et module sont spécifiques à Python.

Exemple

{
  "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 }
  ]
}

Champs

Obligatoires

Champ Type Notes
id string Identifiant unique en DNS inversé. Utilisé partout — activation / désactivation, lignes de journal, réglages par plugin. Ne doit pas changer d'une version à l'autre.
apiVersion integer Doit être égal au MTE_PLUGIN_API_VERSION de l'hôte. Actuellement 1. Une incohérence est signalée dans la page Extensions et le plugin est listé mais non chargé.
entry string Doit valoir "python" pour passer par le backend Python. "native" ou l'absence du champ passe par le chargeur Qt.
module string Nom du module Python contenant register(ctx). Si "main", le worker cherche main.py dans le dossier du plugin. Les noms de paquets avec points ("src.main") sont une extension future — la phase 1 ne prend en charge que les noms plats.

Recommandés

Champ Type Notes
name string Nom d'affichage lisible, montré dans la page Extensions.
version string Semver ; forme libre sinon.
vendor string Auteur / organisation. Affiché dans la page Extensions.
description string Une ou deux lignes. Affichée dans la page Extensions.

Optionnels

Champ Type Notes
order integer Ordre de chargement entre plugins ; plus bas = chargé plus tôt. 1000 par défaut. Les égalités sont départagées par id.
menus tableau d'objets Voir ci-dessous.
pyRequires tableau de chaînes Chaînes d'exigences pip (p. ex. ["requests>=2.31"]). Au premier lancement du plugin, l'éditeur provisionne un environnement virtuel par plugin, y installe ces dépendances via pip et exécute le worker du plugin dedans (voir Empaquetage). Les entrées vides ou non textuelles sont ignorées.
permissions tableau de chaînes Déclarations de capacités à gros grain (p. ex. ["network"]), affichées en lecture seule dans la colonne Permissions de Préférences → Extensions afin que les utilisateurs voient ce que le plugin déclare faire. Déclaratif uniquement — pas encore appliqué.
thirdParty tableau d'objets Composants tiers embarqués par le plugin, pour l'attribution dans la boîte de dialogue À propos. Chaque entrée : name (obligatoire), license, url, file. Livrez le texte de licence nommé par file avec le plugin sous Plugins/Licenses/<id>/. Voir ci-dessous.

Chaque entrée déclare un menu de premier niveau auquel le plugin contribue et fixe sa position. Répétez un objet par menu de premier niveau que vous touchez (Tools, Plugins, Help, etc.).

"menus": [
  { "title": "Plugins", "barPriority": 570, "itemPriority": 100 }
]
Champ Type Notes
title string, obligatoire Le libellé du menu de premier niveau sous lequel vit l'élément (Plugins, Tools, …). Doit correspondre au segment le plus à gauche des chemins que vous passez à ctx.menus.add_item().
barPriority integer, optionnel Rang de gauche à droite dans la barre de menus. Plus bas = plus à gauche. Les menus du cœur ont des priorités fixes espacées de 100 (Fichier 100, Édition 200, …, Fenêtre 600) ; 570 place votre sous-menu près de la position Plugins. Répété entre plugins visant le même menu de premier niveau ; le dernier gagne, ce qui est sans conséquence car idempotent.
itemPriority integer, optionnel Rang vertical de l'ensemble du bloc de votre plugin dans le menu feuille. 1000 par défaut. Plus bas = plus haut.

Vous ne listez PAS les éléments individuels ici — ils sont ajoutés par ctx.menus.add_item() à l'exécution. menus ne concerne que le placement dans la barre de menus.

thirdParty

Déclarez tout composant tiers embarqué par votre plugin afin que la boîte de dialogue À propos puisse l'attribuer. Chaque entrée :

"thirdParty": [
  { "name": "SomeLib", "license": "MIT",
    "url": "https://example.com/", "file": "SomeLib-LICENSE.txt" }
]
Champ Type Notes
name string, obligatoire Le composant. Les entrées sans nom non vide sont ignorées.
license string, optionnel Étiquette de style SPDX, p. ex. MIT, LGPL-3.0.
url string, optionnel Page du projet.
file string, optionnel Nom de base du texte de licence que vous livrez, résolu en Plugins/Licenses/<your-plugin-id>/<file>.

Vous êtes propriétaire des textes de licence : livrez-les avec votre paquet de plugin sous Plugins/Licenses/<id>/. L'éditeur liste les composants et oriente les utilisateurs vers ce dossier ; il ne conserve pas les textes tiers de votre plugin dans son propre dossier Licenses/.

Sonde statique

Au moment de la découverte — et de nouveau lors de l'installation d'un paquet .mteplugin — l'hôte lit module, ouvre <pluginDir>/<module>.py et confirme qu'il contient un def register(...) de niveau module — aucun code n'est exécuté. L'installateur rejette un paquet défaillant avec une boîte de dialogue d'erreur ; la découverte ignore silencieusement le plugin avec une ligne d'erreur dans le journal :

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

Gardez register à la colonne 0 d'une ligne commençant par def register(.

Ordre de chargement et placement dans la barre de menus

Si votre plugin contribue à Plugins avec barPriority: 570, le menu apparaît au rang 570 dans la barre de menus. Deux plugins avec des valeurs de barPriority différentes pour le même titre sont en concurrence : le dernier chargé gagne, mais comme les deux déclarent généralement le même rang pour un menu donné, cela n'a pas d'importance. Voir PLUGIN_ARCHITECTURE.md §13 pour le modèle d'ordonnancement complet.

Ce qui n'a PAS sa place ici

L'hôte analyse les champs documentés ci-dessus et ignore tout le reste — n'inventez pas de champs ; une clé inconnue est un poids mort silencieux.