Manual: Entwickeln von Erweiterungen
Wer Erweiterung auf Wikimedia-Websites bereitstellen möchte, sollte Writing an extension for deployment lesen. |
Jede Erweiterung besteht aus drei Teilen:
Eine minimale Erweiterung besteht aus der folgenden Struktur:
- MyExtension/extension.json
- Speichert die setup-Anleitung. Der Dateiname muss "extension.json" lauten. (Vor MediaWiki 1.25 befanden sich die Setup-Anweisungen in einer
MyExtension/MyExtension.php
-Datei, die nach der Erweiterung benannt wurde. Viele Erweiterungen halten in dieser PHP-Datei noch Abwärtskompatibilitäten bereit.) - MyExtension/includes/ (or MyExtension/src/)
- Enthält den auszuführenden PHP-Code für die Erweiterung.
- MyExtension/resources/ (or MyExtension/modules/)
- Speichert die clientseitigen Ressourcen wie JavaScript, CSS und LESS für die Erweiterung.
- MyExtension/i18n/*.json
- Enthält Lokalisierungsinformation für die Erweiterung.
Wenn du eine Erweiterung entwickelst, ersetze MyExtension durch den tatsächlichen Namen deiner Erweiterung. Benutze UpperCamelCase-Namen für das Verzeichnis und die PHP-Datei(en); das entspricht der allgemeinen Dateinamenskonvention.[1] (Ein guter Ausgangspunkt für eine eigene Erweiterung ist die BoilerPlate extension.)
$wgMainCacheType = CACHE_NONE
und $wgCacheDirectory = false
abzuschalten, sonst werden Systemmeldungen und andere Änderungen möglicherweise nicht angezeigt.
Einrichtung
Dein Ziel beim Schreiben des Setup-Teils ist es, die Installation der Erweiterung so einfach wie möglich zu machen, damit die Benutzer nur diese Zeile zu LocalSettings.php hinzufügen müssen:
wfLoadExtension( 'MyExtension' );
Wenn du deine Erweiterung benutzerkonfigurierbar erstellen willst, musst du einige Konfigurationsparameter definieren und dokumentieren. Die Einstellungen deiner Benutzer sollten in etwa so aussehen:
wfLoadExtension( 'MyExtension' );
$wgMyExtensionConfigThis = 1;
$wgMyExtensionConfigThat = false;
Um diese Einfachheit zu erreichen, muss Ihre Setup-Datei eine Reihe von Aufgaben ausführen (die in den folgenden Abschnitten ausführlich beschrieben werden):
- registriere alle Medienhandler, Parserfunktionen, Spezialseiten, Benutzerdefinierte XML-Tags und Variablen, die von deiner Erweiterung verwendet werden.
- definiere und/oder bestätige alle Variablen, die du für deine Erweiterung definiert hast.
- die von deiner Erweiterung verwendeten Klassen für das Autoloading vorbereiten
- bestimmen, welche Teile deiner Einrichtung sofort erledigt werden sollten und was aufgeschoben werden muss, bis der MediaWiki-Kern initialisiert und konfiguriert wurde
- definiere alle zusätzlichen Hooks, die deine Erweiterung benötigt
- neue Datenbanktabellen erstellen oder überprüfen, die für deine Erweiterung benötigt werden.
- die Lokalisierung für deine Erweiterung festlegen
.md
hinzu. Siehe zum Beispiel die Datei README.md
für Parsoid auf Phabricator Diffusion.
Registrieren von Funktionen bei MediaWiki
MediaWiki listet alle Erweiterungen auf, die auf der Seite Special:Version
installiert wurden.
Beispielsweise können Sie alle in diesem Wiki installierten Erweiterungen unter Special:Version anzeigen.
MediaWiki Version: | ≥ 1.25 |
Um diese zu erreichen, sind die Erweiterungsdetails zu extension.json hinzuzufügen. Der Eintrag sieht ungefähr so aus:
{
"name": "Example",
"author": "John Doe",
"url": "https://www.mediawiki.org/wiki/Extension:Example",
"description": "This extension is an example and performs no discernible function",
"version": "1.5",
"license-name": "GPL-2.0-or-later",
"type": "validextensionclass",
"manifest_version": 1
}
Viele der Felder sind optional, aber es wird immer noch empfohlen, sie auszufüllen.
Das manifest_version
bezieht sich auf die Version des Schemas, gegen die die extension.json Datei geschrieben wird.
Die verfügbaren Versionen sind 1 und 2. Eine Dokumentation zu dieser Funktion findet sich hier.
Wenn du nicht eine ältere Version von MediaWiki unterstützen musst, wähle die neueste Version.
Zusätzlich zu der oben genannten Registrierung müssen Sie Ihre Funktion auch in MediaWiki "einbinden". Das Obige richtet nur die Seite Special: Version ein. Wie du das tust, hängt von der Art deiner Erweiterung ab. Einzelheiten finden Sie in der Dokumentation zu den einzelnen Erweiterungstypen:
Machen Sie Ihre Erweiterung konfigurierbar
Wenn Ihr Benutzer Ihre Erweiterung konfigurieren kann, müssen Sie eine oder mehrere Konfigurationsvariablen angeben. Es ist eine gute Idee, diesen Variablen einen eindeutigen Namen zu geben. Sie sollten auch MediaWiki Namenskonventionen folgen (z. B. sollten globale Variablen mit $wg beginnen).
Wenn die Erweiterung beispielsweise "MeineErweiterung" heißt, liegt es nahe, die Benennung aller Konfigurationsvariablen mit $wgMeineErweiterung
beginnen zu lassen.
Dabei ist wichtig, dass keine des MediaWiki-Kerns seine Variablen auf diese Weise beginnt und in ausreichender Weise überprüft wurde, dass keine der veröffentlichten Erweiterungen ihre Variablen auf diese Weise beginnt.
Benutzer müssen sich nicht zwischen Ihrer Erweiterung und einigen anderen Erweiterungen entscheiden, da Sie überlappende Variablennamen ausgewählt haben.
Es ist auch eine gute Idee, eine ausführliche Dokumentation aller Konfigurationsvariablen in Ihre Installationshinweise aufzunehmen.
Hier ist eine Beispielvorlage, mit der Sie loslegen können:
{
"name": "BoilerPlate",
"version": "0.0.0",
"author": [
"Your Name"
],
"url": "https://www.mediawiki.org/wiki/Extension:BoilerPlate",
"descriptionmsg": "boilerplate-desc",
"license-name": "GPL-2.0-or-later",
"type": "other",
"AutoloadClasses": {
"BoilerPlateHooks": "includes/BoilerPlateHooks.php",
"SpecialHelloWorld": "includes/SpecialHelloWorld.php"
},
"config": {
"BoilerPlateEnableFoo": {
"value": true,
"description": "Enables the foo functionality"
}
},
"callback": "BoilerPlateHooks::onExtensionLoad",
"ExtensionMessagesFiles": {
"BoilerPlateAlias": "BoilerPlate.i18n.alias.php"
},
"Hooks": {
"NameOfHook": "BoilerPlateHooks::onNameOfHook"
},
"MessagesDirs": {
"BoilerPlate": [
"i18n"
]
},
"ResourceModules": {
"ext.boilerPlate.foo": {
"scripts": [
"resources/ext.boilerPlate.js",
"resources/ext.boilerPlate.foo.js"
],
"styles": [
"resources/ext.boilerPlate.foo.css"
]
}
},
"ResourceFileModulePaths": {
"localBasePath": "",
"remoteExtPath": "BoilerPlate"
},
"SpecialPages": {
"HelloWorld": "SpecialHelloWorld"
},
"manifest_version": 2
}
Beachte, dass nach dem Aufruf von wfLoadExtension( 'BoilerPlate' );
die globale Variable $wgBoilerPlateEnableFoo
nicht mehr existiert.
Wenn du die Variable z.B. in LocalSettings.php
festlegst, wird der in der extension.json angegebene Standardwert nicht verwendet.
Weitere Informationen über die Verwendung globaler Variablen in benutzerdefinierten Erweiterungen findest du unter Manual:Configuration for developers .
Klassen für das automatische Laden vorbereiten
Wenn Sie Klassen zum Implementieren Ihrer Erweiterung verwenden, bietet MediaWiki einen vereinfachten Mechanismus, mit dem PHP die Quelldatei finden kann, in der sich Ihre Klasse befindet.
In den meisten Fällen sollte dies die Notwendigkeit beseitigen, eine eigene __autoload($classname)
-Methode zu schreiben.
Um den Autoload-Mechanismus von MediaWiki zu nutzen, fügst du Einträge in das Feld AutoloadClasses ein. Der Schlüssel jedes Eintrags ist der Klassenname. Der Wert ist die Datei, in der die Definition der Klasse gespeichert ist. Bei einer einfachen Ein-Klassen-Erweiterung erhält die Klasse normalerweise denselben Namen wie die Erweiterung, so dass dein Autoloading-Abschnitt etwa so aussehen könnte (die Erweiterung heißt MyExtension):
{
"AutoloadClasses": {
"MyExtension": "includes/MyExtension.php"
}
}
Der Dateiname bezieht sich auf das Verzeichnis, in dem sich die Datei extension.json befindet.
Für komplexere Erweiterungen sollten Namensräume in Betracht gezogen werden. Siehe Manual:Extension.json/Schema#AutoloadNamespaces für Details.
Zusätzliche Hooks definieren
Siehe Handbuch:Hooks .
Datenbank Tabellen hinzufügen
Stelle sicher, dass die Erweiterung die Hauptdatenbanktabellen nicht verändert. Stattdessen sollte die Erweiterung neue Tabellen mit Fremdschlüsseln zu den entsprechenden MW-Tabellen erstellen.
Wenn deine Erweiterung ihre eigenen Datenbanktabellen hinzufügen muss, verwende den Haken LoadExtensionSchemaUpdates . Weitere Informationen zur Verwendung finden Sie auf der Handbuchseite.
Lokalisierung einrichten
Siehe:
Logs hinzufügen
In MediaWiki werden alle Aktionen von Benutzern im Wiki auf Transparenz und Zusammenarbeit hin verfolgt. Siehe Manual:Logging to Special:Log für die Durchführung.
Umgang mit Abhängigkeiten
Angenommen, eine Erweiterung erfordert das Vorhandensein einer anderen Erweiterung, z.B. weil Funktionalitäten oder Datenbanktabellen genutzt werden sollen und Fehlermeldungen bei Nichtvorhandensein vermieden werden sollen.
Zum Beispiel erfordert die Erweiterung CountingMarker für bestimmte Funktionen das Vorhandensein der Erweiterung HitCounters .
Eine Möglichkeit, dies anzugeben, wäre die Verwendung des Schlüssels requires
in extension.json.
Eine andere Möglichkeit ist die Verwendung von ExtensionRegistry (verfügbar seit MW 1.25):
if ( ExtensionRegistry::getInstance()->isLoaded( 'HitCounters', '>=1.1' ) {
/* do some extra stuff, if extension HitCounters is present in version 1.1 and above */
}
Currently (as of February 2024, MediaWiki 1.41.0) the name of the extension-to-be-checked needs to exactly match the name in their extension.json.[2][3]
Example: if you want to check the load status of extension "OpenIDConnect", you have to use it with a space
if ( ExtensionRegistry::getInstance()->isLoaded( 'OpenID Connect' ) {
...
}
Lokalisierung
|
$wgMainCacheType = CACHE_NONE
und $wgCacheDirectory = false
festlegst, sonst werden deine Änderungen an den Systemmeldungen möglicherweise nicht angezeigt.Wenn Sie möchten, dass Ihre Erweiterung in Wikis mit mehrsprachiger Leserschaft verwendet wird, müssen Sie Ihrer Erweiterung Lokalisierungsunterstützung hinzufügen.
Speichern Sie Nachrichten in <Sprachschlüssel>.json
Speichern Sie Nachrichtendefinitionen in einer Lokalisierungs-JSON-Datei, eine für jeden Sprachschlüssel, in den Ihre Erweiterung übersetzt wird. Die Nachrichten werden mit einem Nachrichtenschlüssel und die Nachricht selbst im Standard-JSON-Format gespeichert. Jede Nachrichten-ID sollte in Kleinbuchstaben geschrieben sein und darf keine Leerzeichen enthalten. Jeder Schlüssel sollte mit dem Namen der Erweiterung in Kleinbuchstaben beginnen. Ein Beispiel findet sich in der MobileFrontend-Erweiterung. Hier ist ein Beispiel für eine minimale JSON-Datei (in diesem Fall en.json:
en.json
{
"myextension-desc": "Adds the MyExtension great functionality.",
"myextension-action-message": "This is a test message"
}
Speichern Sie die Nachrichtendokumentation in qqq.json
Die Dokumentation für Nachrichtenschlüssel kann in der JSON-Datei für die Pseudosprache mit dem Code qqq gespeichert werden. Eine Dokumentation des obigen Beispiels kann sein:
qqq.json:
{
"myextension-desc": "The description of MyExtension used in Extension credits.",
"myextension-action-message": "Adds 'message' after 'action' triggered by user."
}
Laden Sie die Lokalisierungsdatei
In der extension.json ist der Speicherort der Nachrichtendateien (z. B. im Verzeichnis i18n/) festzulegen:
{
"MessagesDirs": {
"MyExtension": [
"i18n"
]
}
}
Verwenden Sie wfMessage in PHP
Ersetzen Sie in Ihrem Setup- und Implementierungscode jede wörtliche Verwendung der Nachricht durch einen Aufruf von wfMessage( $msgID, $param1, $param2, ... )
.
In Klassen, die IContextSource implementieren (sowie in einigen anderen, z. B. Unterklassen von SpecialPage), können Sie stattdessen $this->msg( $msgID, $param1, $param2, ... )
verwenden.
Beispiel:
wfMessage( 'myextension-addition', '1', '2', '3' )->parse()
Verwenden Sie mw.message in JavaScript
Es ist auch möglich, i18n-Funktionen in JavaScript zu verwenden. Schau dir Handbuch:Messages-API für Details an.
Erweiterungstypen
Erweiterungen können basierend auf den Programmiertechniken kategorisiert werden, mit denen ihre Wirkung erzielt wird. Die meisten komplexen Erweiterungen verwenden mehr als eine dieser Techniken:
- Unterklasse: MediaWiki erwartet, dass bestimmte Arten von Erweiterungen als Unterklassen einer von MediaWiki bereitgestellten Basisklasse implementiert werden:
- Spezialseiten – Unterklassen der SpecialPage -Klasse werden zum Erstellen von Seiten verwendet, deren Inhalt mithilfe einer Kombination aus dem aktuellen Systemstatus, Benutzereingabeparametern und Datenbankabfragen dynamisch generiert wird. Es können sowohl Berichte als auch Dateneingabeformulare generiert werden. Sie werden sowohl für Berichts- als auch für Verwaltungszwecke verwendet.
- Oberflächen – Skins ändern das Erscheinungsbild von MediaWiki, indem sie den Code ändern, der Seiten ausgibt, indem sie die MediaWiki-Klasse SkinTemplate unterordnen.
- Hooks – Eine Technik zum Einfügen von benutzerdefiniertem PHP-Code an wichtigen Punkten der MediaWiki-Verarbeitung. Sie werden häufig vom Parser von MediaWiki, seiner Lokalisierungs-Engine, seinem Erweiterungsverwaltungssystem und seinem Seitenpflegesystem verwendet.
- Tag-Funktions-Assoziationen – XML Stil-Tags, die einer PHP-Funktion zugeordnet sind, die HTML-Code ausgibt. Sie müssen sich nicht darauf beschränken, den Text in den Tags zu formatieren. Sie müssen es nicht einmal anzeigen. Viele Tag-Erweiterungen verwenden den Text als Parameter für die Generierung von HTML, in das Google-Objekte, Dateneingabeformulare, RSS-Feeds und Auszüge aus ausgewählten Wiki-Artikeln eingebettet sind.
- Magische Wörter – Eine Technik zum Zuordnen einer Vielzahl von Wiki-Textzeichenfolgen zu einer einzelnen ID, die einer Funktion zugeordnet ist. Sowohl Variablen als auch Parser-Funktionen verwenden diese Technik. Der gesamte dieser ID zugeordnete Text wird durch den Rückgabewert der Funktion ersetzt. Die Zuordnung zwischen den Textzeichenfolgen und der ID wird im Array $magicWords gespeichert. Die Interpretation der ID ist ein etwas komplexer Prozess - siehe Handbuch:Magische Wörter für weitere Informationen.
- Variable – Variablen sind eine Art Fehlbezeichnung. Es handelt sich um Wikitext-Bits, die wie Vorlagen aussehen, jedoch keine Parameter haben und fest codierte Werte erhalten haben. Standard-Wiki-Markups wie
{{PAGENAME}}
oder{{SITENAME}}
sind Beispiele für Variablen. Sie erhalten ihren Namen von der Quelle ihres Wertes: eine PHP-Variable oder etwas, das einer Variablen zugewiesen werden könnte, z. eine Zeichenfolge, eine Zahl, ein Ausdruck oder ein Funktionsrückgabewert. - Parser-Funktionen –
{{functionname: argument 1 | argument 2 | argument 3...}}
. Ähnlich wie bei Tag-Erweiterungen verarbeiten Parser-Funktionen Argumente und geben einen Wert zurück. Im Gegensatz zu Tag-Erweiterungen ist das Ergebnis von Parser-Funktionen wikitext.
- Variable – Variablen sind eine Art Fehlbezeichnung. Es handelt sich um Wikitext-Bits, die wie Vorlagen aussehen, jedoch keine Parameter haben und fest codierte Werte erhalten haben. Standard-Wiki-Markups wie
- API Module – Du kannst benutzerdefinierte Module zu MediaWikis Action API hinzufügen, die von JavaScript, Bots oder Drittanbieter-Clients aufgerufen werden können.
- Page content models – Wenn du Daten in anderen Formaten als wikitext, JSON usw. laden willst, kannst du einen neuen ContentHandler erstellen.
Unterstützt andere Kernversionen
Es gibt zwei weit verbreitete Konventionen zur Unterstützung älterer Versionen von MediaWiki Core:
- Master: Der Master Branch der Erweiterung ist mit so vielen alten Versionen von Core wie möglich kompatibel. Dies führt zu einem gewissen Wartungsaufwand (Abwärtskompatibilitäts-Hacks müssen lange aufrechterhalten werden, und Änderungen an der Erweiterung müssen mit mehreren MediaWiki-Versionen getestet werden), Websites, die alte MediaWiki-Versionen ausführen, profitieren jedoch von den kürzlich hinzugefügten Funktionen der Erweiterung.
- Veröffentlichungszweige: Die Veröffentlichungszweige der Erweiterung sind mit den entsprechenden Zweigen des Kerns kompatibel, d.h. Websites, die MediaWiki 1.42 verwenden, müssen den REL1_42 Branch der Erweiterung verwenden. (Für Erweiterungen, die auf Gerrit gehostet werden, werden diese Branches automatisch erstellt, wenn neue Versionen von MediaWiki veröffentlicht werden). Dies führt zu saubererem Code und schnellerer Entwicklung, jedoch profitieren Nutzer alter Kernversionen nicht von Bugfixes und neuen Funktionen, es sei denn, sie werden manuell backported.
Die Betreuer von Erweiterungen sollten mit dem Parameter compatibility policy
der Vorlage {{Erweiterung }} angeben, welcher Konvention sie folgen.
Lizenz
MediaWiki is an open-source project and users are encouraged to make any MediaWiki extensions under an Open Source Initiative (OSI) approved license compatible with GPL-2.0-or-later (Wikimedia's standard software license).
We recommend adopting one of the following compatible licenses for your projects in Gerrit:
- GNU General Public License, Version 2 oder neuer (GPL-2.0-or-later)
- MIT-Lizenz (MIT)
- BSD-Lizenz (BSD-3-Clause)
- Apache License 2.0 (Apache-2.0)
For extensions that have a compatible license, you can request developer access to the MediaWiki source repositories for extensions.
To specify the licence in code and with "license-name
" a key should be used to provide it's short name, e.g. "GPL-2.0-or-later" or "MIT" adhering to the list of identifiers at spdx.org.
Veröffentlichung
Um die Dokumentation deiner bestehenden Erweiterung automatisch zu kategorisieren und zu standardisieren, beachte bitte Vorlage:Erweiterung . So fügen Sie Ihrem Wiki Ihre neue Erweiterung hinzu:
Ein Entwickler, der sein Code im MediaWiki-Coderepositorium teilt, sollte folgendes erwarten:
- Rückmeldung / Kritik / Code-Überprüfungen
- Review and comments by other developers on things like framework use, security, efficiency and usability.
- Developer tweaking
- Other developers modifying your submission to improve or clean-up your code to meet new framework classes and methods, coding conventions and translations.
- Improved access for wiki sysadmins
- If you do decide to put your code on the wiki, another developer may decide to move it to the MediaWiki code repository for easier maintenance. You may then create a Entwicklerkonto to continue maintaining it.
- Zukünftige Versionen von anderen Entwicklern
- New branches of your code being created automatically as new versions of MediaWiki are released. You should backport to these branches if you want to support older versions.
- Incorporation of your code into other extensions with duplicate or similar purposes — incorporating the best features from each extension.
- Credit
- Credit for your work being preserved in future versions — including any merged extensions.
- Similarly, you should credit the developers of any extensions whose code you borrow from — especially when performing a merger.
Any developer who is uncomfortable with any of these actions occurring should not host in the code repository. You are still encouraged to create a summary page for your extension on the wiki to let people know about the extension, and where to download it.
Bereitstellen und Registrieren
Wenn Sie beabsichtigen, Ihre Erweiterung auf Wikimedia-Websites (einschließlich möglicherweise Wikipedia) bereitzustellen, ist eine zusätzliche Prüfung in Bezug auf Leistung und Sicherheit erforderlich. Konsultiere Writing an extension for deployment .
Wenn deine Erweiterung Namensräume hinzufügt, möchtest du vielleicht ihre Standard-Namensräume registrieren; wenn sie Datenbanktabellen oder -felder hinzufügt, möchtest du diese vielleicht unter Datenbankfeld-Präfixe registrieren.
Bitte beachten Sie, dass die Überprüfung und Bereitstellung neuer Erweiterungen auf Wikimedia-Websites sehr langsam sein kann und in einigen Fällen mehr als zwei Jahre gedauert hat. [4]
Hilfedokumentation
Sie sollten Public-Domain-Hilfedokumentation für Funktionen bereitstellen, die von Ihrer Erweiterung bereitgestellt werden.
The convention is for extensions to have their user-focused help pages under a pseudo-namespace of Help:Extension:<ExtensionName>
, with whatever subpages are required (the top level page will be automatically linked from the extension infobox if it exists).
Help:CirrusSearch/de ist ein gutes Beispiel.
Sie sollten Benutzern über die Funktion addHelpLink() einen Link zur Dokumentation geben.
Releasing updates
There are a number of common approaches to releasing updates to extensions.
These are generally defined according to the compatibility policy of the extension (master
, rel
, or ltsrel
):
master
- Releases may be tagged with version numbers on the master branch, and documentation provided on the extension's homepage describing which extension versions are compatible with which core versions. Release branches will still be created automatically, and you may wish to delete these if they are not intended to be used.rel
andltsrel
- Release by backporting changes to theREL1_*
branches (either all changes, or only critical ones). Version numbers are generally not needed unless the extension is a dependency of another (the version number can then be provided in the other extension's configuration to ensure that incompatible combinations aren't installed). Many extensions will stay at the same version number for years.
Bereitstellung von Unterstützung/Zusammenarbeit
Erweiterungsentwickler sollten ein Konto bei Wikimedia Phabricator eröffnen und ein neues Projekt für die Erweiterung anfordern. Dies bietet einen öffentlichen Ort, an dem Benutzer Probleme und Vorschläge einreichen können, und Sie können mit Benutzern und anderen Entwicklern zusammenarbeiten, um Fehler zu ermitteln und Funktionen Ihrer Erweiterung zu planen.
Siehe auch
- Manual:Erweiterungsregistrierung - provides further developer documentation on how to register extensions and skins.
- API:Erweiterungen – erklärt, wie Ihre Erweiterung Clients eine API bereitstellen kann
- Manual:Extending wiki markup
- Manual:Kodierungskonventionen
- Beste Praktiken für Erweiterungen
- ResourceLoader
Learn by example
- Erweiterung:Examples – implementiert einige Beispielfunktionen mit umfangreicher Inline-Dokumentation
- Extension:BoilerPlate – Eine funktionierende Boilerplate-Erweiterung, die als Ausgangspunkt für Ihre eigene Erweiterung dient (git repo)
- Lesen Sie die Beispielerweiterung und stützen Sie Ihren eigenen Code auf die BoilerPlate-Erweiterung.
- cookiecutter-mediawiki-extension – eine cookiecutter Vorlage, die eine Boilerplate-Erweiterung generiert (mit Variablen usw.)
- Ermöglicht es Ihnen, mit Ihrer eigenen Erweiterung schnell loszulegen.
- Kann auch die BoilerPlate-Erweiterung generieren.
- List of simple extensions - Kopieren Sie bestimmten Code von ihnen