Eigene Auszeichnungen

für die Liste aller Seiten

Administratoren (FTP)

Einführung

Die Auszeichnungsumwandlung wird bei PmWiki durch einen Satz von Regeln gesteuert. Jede Regel definiert eine bestimmte Zeichenkette, nach der der Wikitext durchsucht wird. Die gefundene Stelle wird durch einen anderen Text ersetzt. Intern wird das mit der PHP-Funktion "preg_replace" verwirklicht.

Zusätzliche Regeln werden in PmWiki der Übersetzungsmaschine mit den PmWiki-Funktionen Markup() oder Markup_e() bekannt gemacht. Diese sehen folgendermaßen aus:

Markup($name, $wann, $muster, $ersetzung); # wenn keine Evaluation nötig ist oder wenn PHP < 5.5
Markup($name, $wann, $muster, $ersetzungs_funktion); # wenn Evaluation nötig ist

# %red%MISSBILLIGT%%, ab PHP 7.2 nicht mehr vorhanden
[@Markup_e($name, $wann, $muster, $ersetzung); # wenn Evaluation nötig ist und 5.5 <= PHP <= 7.1
  • $name ist ein eindeutiger Name (Zeichenfolge) für die Regel,
  • $wann legt fest, wann die Regel im Vergleich zu den anderen Regeln ausgeführt werden soll,
  • $muster enthält das Suchmuster, nach dem im Markuptext (dem Wikiquelltext) gesucht wird,
  • $ersetzung ist die Zeichenfolge, durch die das gefundene Muster ersetzt werden soll und
  • $ersetzungs_funktion ist der Name der Funktion, die mit der Übereinstimmung aufgerufen werden und die Ersetzung zurückliefern soll.

Beispiel

Als Beispiel hier der Programmcode, der die Regel für ''hervorgehobener Text'' (in scripts/stdmarkup.php) erzeugt:

Markup("em", "inline", "/''(.*?)''/", "<em>$1</em>");

Diese Anweisung erstellt eine Regel, die "em" heißt, welche zusammen mit anderen "inline" Auszeichnungen ausgeführt wird. Die Regel ersetzt den Text innerhalb zweier Paare einfacher Anführungszeichen durch eben diesen Text ($1), jedoch eingeschlossen von <em> und </em>.

Name und Reihenfolge

Die ersten beiden Parameter von Markup() legen die Reihenfolge der Anwendung der Regeln fest. Der erste Parameter gibt der Regel einen Namen – "em" im obigen Beispiel. Man könnte einen beliebigen anderen Namen benutzen, etwa "''" oder sogar "zweieinfachehochkommata". Im Allgemeinen benutzt PmWiki das Markup selbst als Namen der Regel (d.h. PmWiki würde "''" und nicht "em" benutzen), aber im Interesse der Lesbarkeit im Folgenden benutzen wir hier einen mnemonischen Namen.

Der zweite Parameter sagt, dass die Regel zusammen mit anderen "inline" Auszeichnungen bearbeitet werden soll. PmWiki teilt den Übersetzungsvorgang in mehreren Phasen auf:

  _begin      Beginn der Umwandlung
  {$var}      Verarbeitung der Seiten-Text-Variablen
  fulltext    Verarbeitung des gesamten Eingabetextes
  split       Zerteilen des Eingabetextes in einzelne, zu verarbeitende Zeilen
  directives  Verarbeitung von Direktiven
  inline      Übersetzung von im Text auftauchenden Auszeichnungen
  links       Übersetzung von Verweisen, Internetadressen und Wikiwörtern
  block       Übersetzung von Block-Auszeichnungen
  style       Umsetzung von Stilen
  _end        Ende der Umwandlung

Dies Argument wird normalerweise als öffnende spitze Klammer ("vorher") oder schließende spitze Klammer ("nachher") angegeben, gefolgt vom Namen einer anderen Regel.

Die Angabe "inline" als zweiter Parameter bedeutet somit, dass die Regel zusammen mit anderen "inline" Regeln verarbeitet wird. Soll die Regel dagegen zusammen mit den Direktiven verarbeitet werden, d. h. bevor die inline-Regeln verarbeitet werden, müsste man "directives" oder "<inline" als zweiten Parameter angeben.

{$var}- und (:if ...:)-Bedingungen

Eine signifikante Regel in Sachen Reihenfolge ist "{$var}", wo Variablen ersetzt werden – wenn es heißt "<{$var}", dann wird Ihr Markup bearbeitet, bevor Variablen ersetzt werden, wohingegen ">{$var}" bedeutet, dass Ihr Markup bearbeitet wird, nachdem die Variablen ersetzt wurden. Das passiert noch vor Bedingungsausdrücken (:if...:), weshalb Seitentextvariablen ausgewertet werden, selbst wenn sie innerhalb eines (:if false:)-Segments definiert wurden.

Definition des regulären Ausdrucks im Markup

Der dritte Parameter ist ein Perl-kompatibler regulärer Ausdruck. Genau genommen ist es ein Schrägstrich, ein regulärer Ausdruck, ein weiterer Schrägstrich und (optional) einige Modifikatoren.

Das Beispiel verwendet das Suchmuster "/''(.*?)''/", das ''(.*?)'' als regulären Ausdruck ohne weitere Optionen enthält. (Der reguläre Ausdruck sagt: "Finde zwei aufeinander folgende einfache Anführungszeichen, dann so wenig beliebige Zeichen wie möglich, damit das Suchmuster zutrifft, danach wieder zwei aufeinander folgende einfache Anführungszeichen". Die Klammern "kopieren" einen Teil des Wikitextes für die spätere Verwendung in eine "Zwischenablage".)

Ersetzungstext

Der vierte Parameter ist der Ersetzungstext, der anstatt des kompletten Suchmusters (Auszeichnung und Wikitext) angezeigt werden soll. Man kann $1, $2 usw. verwenden, um den Text aus dem ersten, zweiten usw. geklammerten Bereich innerhalb des Textes im regulären Ausdruck einzufügen.

In diesem Beispiel wird "<em>$1</em>" verwendet, das aus <em>, dem gefundenen Text innerhalb der ersten Klammer (d.h. den Teil .*? des Musters) und </em> besteht.

Weitere Beispiele

Hier die Regel für @@Schreibmaschinenschrift@@:

Markup("@@", "inline", "/@@(.*?)@@/", "<code>$1</code>");

und für eine [:comment ...:] Direktive, die einfach bei der Ausgabe entfernt wird:

Markup("comment", "directives", "/\\[:comment .*?:\\]/", '');

Aber wie funktioniert das bei der '''starken Hervorhebung'''? Hier muss man etwas vorsichtig sein. Zwar wird diese zusammen mit andere Inline-Auzeichnungen bearbeitet, aber es muss auch sichergestellt werden, dass die Regel ''' vor der Regel '' bearbeitet wird, da ''' auch '' enthält. Der zweite Parameter von Markup() kann auch benutzt werden, um die Beziehung einer Regel zu einer anderen festzulegen:

Markup("strong", "<em", "/'''(.*?)'''/", "<strong>$1</strong>");

Dies erzeugt eine Regel mit Namen "strong" und der zweite Parameter "<em" legt fest, dass die Regel vor der weiter oben gezeigten "em"-Regel verarbeitet werden soll. Um etwas nach der "em"-Regel auszuführen, würde man stattdessen ">em" verwenden. Damit ist es möglich, Erweiterungen an jeder Stelle der Umwandlung von Auszeichnungen vorzunehmen. (Genau genommen sind "inline", "block", "directives" usw. nur Platzhalter um den Gesamtablauf zu strukturieren, sodass andere Regeln an passender Stelle eingefügt werden können. So kann etwa "<inline" benutzt werden, damit eine Regel vor anderen "inline" Regeln angewendet wird.)

Wenn Sie verfügbare Auszeichnungen abschalten wollen, schreiben sie einfach z. B.:

DisableMarkup("strong");

Die vordefinierten Auszeichnungen von PmWiki sind in scripts/stdmarkup.php definiert. Um die gesamte Ersetzungstabelle während der Programmausführung auszugeben, gibt es das Modul scripts/diag.php das die Aktion "?action=ruleset" zur Verfügung stellt. Damit werden die festgelegten Regeln in der Reihenfolge angezeigt, in der sie verarbeitet werden. Man sieht dies z. B. in Eigene Auszeichnungen?action=ruleset. Sie müssen vorher die Aktion aktivieren durch das Einstellen von $EnableDiag = 1 in Ihrer Konfigurationsdatei.

Weitere gängige Beispiele

Definieren einer eigenen Funktion, die eine spezielle HTML- oder Javascript-Sequenz erzeugt

Angenommen, ein Admin möchte eine einfache "(:example:)"-Auszeichnung haben, die immer eine feste HTML-Zeichenkette in der Ausgabe erzeugt, etwa für einen Webring, Google-AdSense-Display oder Javascript. Der Markup()-Aufruf, der das bewirkt, wäre

Markup('example', 'directives',
  '/\\(:example:\\)/',
  Keep("<div class='example'><p>Here is a 
    <a target='_blank' href='http://www.example.com'>link</a> to
    <em>example.com</em></p></div>") );
  • Das erste Argument ist ein einzigartiger Name für die Auszeichnung ("example").
  • Das zweite Argument sagt, führe diese Auszeichnung zusammen mit anderen Direktiven durch.
  • Das dritte Argument ist das Suchmuster "(:example:)".
  • Das vierte Argument ist die HTML-Zeichenkette, durch die das Suchmuster ersetzt wird. Wir benutzen hier die Keep()-Funktion, um die Ausgabe davor zu schützen, von nachfolgenden Regeln bearbeitet zu werden – im obigen Beispiel wollen wir nicht, dass der http://www.example.com-URL wieder in einen Link verwandelt wird.

Aufruf einer eigenen Funktion, die etwas zurück liefert

Der /e-Modifizierer ist überholt und sollte in aktuellen Entwicklungen nicht eingesetzt werden. Siehe unten wegen weiterer Details.

Für ältere PHP-Versionen (< 7.2) veranlasst die 'e'-Option beim Parameter $muster PmWiki, den Parameter $ersetzung nicht als Ersetzungstext, sondern als PHP-Ausdruck zu interpretieren, der den Ersetzungsausdruck zurückliefert. Um den Gebrauch des missbilligten 'e'-Parameters zu vermeiden, sähe ein Markup, das eine Zahl zwischen 1 und 100 liefert,m so aus:

Markup('random', 'directives',
  '/\\(:random:\\)/',
  "MyRandomFunction");
function MyRandomFunction() {
  return rand(1, 100);
}

Dies ruft die PHP-interne rand()-Funktion auf und ersetzt die Direktive mit dem Ergebnis. Jede Funktion kann aufgerufen werden, einschließlich der Funktionen, die in einer Datei für Lokale Anpassungen oder in einem Kochbuch-Rezept definiert wurden.

Argumente können auch übergeben werden, indem reguläre Ausdrücke einfangende Klammern benutzt werden, so bewirkt die Auszeichnung

Markup('randomargs', 'directives',
  '/\\(:random (\\d+) (\\d+):\\)/',
  "MyRandomFunction");
function MyRandomFunction($m) {
  return rand($m[1], $m[2]);
}

dass die Direktive (:random 50 100:) eine Zufallszahl zwischen 50 und 100 erzeugt.

Beachten Sie: Der 'e'-Modifizierer in regulären Ausdrücken ist seit PHP Version 5.5 verpönt und ab PHP Version 7 entfernt. Der Grund ist, dass arglistige Autoren in der Lage sein könnten, Zeichenketten zu übergeben, die die Ausführung eigenmächtiger und unerwünschter Funktionen bewirkt.

Wegen einer PmWiki-Funktion, die hilft, beliebige Sequenzen aus Schlüssel-Wert-Paaren zu parsen, siehe Cookbook:ParseArgs.

Migration zu PHP 5.5 und Markup_e()

Seit PHP Version 5.5 wird der /e-Auswertungs-Modifier missbilligt und einige Hoster erlauben seine Verwendung nicht mehr.

Jüngere Versionen des PmWiki-Kerns (2.2.58 und jünger) erlauben neue Wege, um Auszeichnungsregeln zu definieren, ohne auf den Modifier /e zurückgreifen zu müssen. Die historischen Wege, Auszeichnungsregeln zu definieren, wurden nicht entfernt und laufen weiterhin, aber sie könnten mit PHP-5.5-Installationen unverträglich sein.

Beachten Sie: Wenn ihr Ersatzmuster nicht ausgewertet werden muss, sollten Sie Markup() benutzen wie bisher und nicht Markup_e(). Das letztere ist verpönt und sollte nicht länger für neue Rezepte und Anpassungen verwendet werden. Alte Rezepte, die Markup_e verwenden, sollten aufgewertet werden und das neue Format benutzen.

DIE KURZFASSUNG: Wenn der reguläre Ausdruck Ihres Markups (das dritte Argument) ein "e" hinter dem schließenden Schrägstrich (d. h. /regex/e oder /regex/se oder entsprechendes) UND Ihr viertes Argument ist vollständig umgeben von doppelten Anführungszeichen, dann kommen Sie aus der Sachen raus, indem Sie einfach die folgenden simplen Schritte unternehmen:

  1. Löschen Sie das "e" in den dritten Argument hinter dem Schrägstrich.
  2. Erzeugen Sie eine Ersetzungsfunktion mit $m als Argument.
  3. In Ihrer Funktion finden sich die ursprünglichen Vorkommen von '$1', '$2', etc. als '$m[1] '$m[2]', etc. wieder.
  4. Setzen Sie den Namen Ihrer Ersetzungsfunktion als viertes Argument des Markup()-Aufrufs ein.

In manchen Fällen reicht das nicht aus – das hängt davon ab, wie das Anführen gemacht wird – aber in vielen Fällen wird das Befolgen dieser einfachen Schritte zu der Verträglichkeit mit PHP 5.5+ führen.

Wenn Sie diese Schritte befolgt haben und dennoch Probleme haben, dann fahren Sie fort zu lesen für ein tieferes Verständnis.

Das Folgende ist akzeptabel für PHP 5.5+ (verträglich mit PmWiki 2.2.58+, läuft auch mit PHP 5.4 und älter)

  • Markup($name, $wann, $muster, $ersetzung);
    • $muster darf keinen "/e"-Modifizierer mehr enthalten
    • $ersetzung kann eine Zeichenkette mit Übereinstimmungen wie $1, $2 etc. sein,
    • $ersetzung kann der Name einer Funktion sein (callback), die mit dem Array der Übereinstimmungen als Argument aufgerufen wird.
    • Anstelle einer Zeichenkette kann der vierte Parameter auch eine anonyme Funktion sein (Beachten Sie: Sie können anonyme Funktionen auf diese Weise seit PHP 5.3.0+ benutzen)
    • Für PHP 5.4 oder früher kann $muster einen /e-Modifier enthalten.
  • Markup_e($name, $wann, $muster, $ersetzung); VERPÖNT, sollte nicht länger eingesetzt werden

Beispiele:

  • Für PHP 5.4 und älter war dies akzeptabel:
    Markup('randomargs', 'directives',
      '/\\(:random (\\d+) (\\d+):\\)/e',
      "rand('$1', '$2')"
      );
  • Für PHP 5.5 und jünger ist $ersetzung der Name einer (callback-) Funktion, wir rufen markup() auf:
    Markup('randomargs', 'directives',
      '/\\(:random (\\d+) (\\d+):\\)/',
      "MyRandom"
      );
    function MyRandom($matches) {
      return rand($matches[1], $matches[2]);
    }
    
Das läuft auch unter PHP 5.4 und älter.

Ein weiteres Beispiel:

  • PHP 5.4 oder älter:
    Markup('Maxi:','<links',
      "/\\b([Mm]axi:)([^\\s\"\\|\\[\\]]+)(\"([^\"]*)\")?/e",
      "Keep(LinkMaxi(\$pagename,'$1','$2','$4','$1$2'),'L')"
      );
    
  • PHP 5.5 oder neuer, PmWiki 2.2.58+, $ersetzung ist der Name einer Funktion:
    Markup('Maxi:','<links',
      "/\\b([Mm]axi:)([^\\s\"\\|\\[\\]]+)(\"([^\"]*)\")?/",
      "LinkMaxi"
      );
    function LinkMaxi($m) {
      extract($GLOBALS['MarkupToHTML']); # to get $pagename
      # do stuff with $m[1], $m[2], etc.
      return Keep($out, 'L');
    }
    
Das läuft auch unter PHP 5.4 und älter.
  • $ersetzung kann auch eine callback-Funktion sein, wir rufen Markup() auf:
    Markup('Maxi:','<links',
      "/\\b([Mm]axi:)([^\\s\"\\|\\[\\]]+)(\"([^\"]*)\")?/",
      "CallbackMaxi"
    );
    function CallbackMaxi($m) {
      extract($GLOBALS["MarkupToHTML"]); # to get $pagename
      return Keep(LinkMaxi($pagename,$m[1],$m[2],$m[4],$m[1].$m[2]),'L');
    }
    
Das läuft auch unter PHP 5.4 und älter.

Das Obige mag kompliziert erscheinen, aber es ist tatsächlich einfacher, Sie benutzen ihre eigene callback-Funktion.

Markup('mykey', 'directives', 
  '/\\(:mydirective (.*?) (.*?):\\)/i',
  'MyFunction'
);
function MyFunction($matches) {
  extract($GLOBALS["MarkupToHTML"]);

  # ... do stuff with $matches ...

  return $out; # oder return Keep($html);
}

Wenn Sie irgendwelche Fragen haben bezüglich des neuen Weges, mit dem man eigene Markup-Funktionen definiert, fragen Sie uns auf der Talk-Seite oder der Mailingliste.

FAQ

Wie kann ich JavaScript in die Ausgabe einer Seite einfügen?

Es gibt mehrere Wege, das zu erreichen. Das Cookbook:JavaScript-Rezept beschreibt ein einfaches Verfahren, um statisches JavaScript in eine Webseite einzufügen mit Hilfe von eigenen Auszeichnungen. Um JavaScript direkt in Wikiseiten zu schreiben (was verschiedene Sicherheitsrisiken öffnen kann), siehe das JavaScript-Editable-Rezept. Für JavaScript, das im Kopf- und Fußbereich von Seiten erscheinen soll, können Sie die skin-Vorlage direkt verändern, oder Sie fügen <script>-Anweisungen ein, indem Sie das $HTMLHeaderFmt-Array benutzen.

Wie erstelle ich ein Markup ((:nodiscussion:)), das eine Seitenvariable ({$HideDiscussion}) setzt, die wiederum mit (:if enabled HideDiscussion:) in .PageActions? eingesetzt werden kann?

Fügen Sie den folgenden Kodeabschnitt in Ihre config.php ein:

SDV($HideDiscussion, 0); 	#define var name
Markup('hideDiscussion', '<{$var}',
 '/\\(:nodiscussion:\\)/', 'setHideDiscussion'); 
function setHideDiscussion() { 
  global $HideDiscussion; 
  $HideDiscussion = true;
} 

Das macht es möglich, die (:if enabled HideDiscussion:)-Auszeichnung einzusetzen. Wenn Sie den aktuellen Wert von {$HideDiscussion} auf der Seite anzeigen wollen (für Testzwecke), müssen Sie auch die Zeile
->$FmtPV['$HideDiscussion'] = '$GLOBALS["HideDiscussion"]';
hinzufügen.

Anscheinend trifft (.*?) in den Funktionen nicht auf Zeilenumbrüche zu, sodass das obige Beispiel nicht funktioniert, wenn der Text, der in <em> eingeklammert werden soll, Zeilenumbrüche enthält.

Wenn Sie den "s"-Modifier im regulären Ausdruck verwenden, wird der Punkt (.) auf einen Zeilenumbruch passen. So wird Ihr regulärer Ausdruck zu "/KRAMS(.*?)/s". Das "s" ganz am Ende ist es, wonach Sie suchten. Wenn Sie beginnen, sich mit mehrzeiligen Ausdrücken zu beschäftigen, sollten Sie sich auch mal die m-Option anzusehen – durch sie passen die Anker (^und $) nicht nur auf den Beginn und das Ende der Zeichenkette, sondern auch auf den Beginn und das Ende von Zeilen, also unmittelbar vor und hinter dem Zeilenumbruch. Versichern Sie sich auch, dass Ihr Markup während der Volltextphase ausgeführt wird.

Wie kann der Text, den meine Markup-Funktion zurückliefert, noch einmal den Markup-Prozess durchlaufen?

Wenn das Ergebnis Ihres Markups weitere Markups enthält, die auch noch behandelt werden sollen, haben Sie zwei Optionen. Die erste ist, ein "wann"-Argument zu wählen, dass vor dem Markup in Ihrem Ergebnis bearbeitet wird. Wenn zum Beispiel Ihr Markup [[links]] zurückliefert, könnte Ihr "wann"-Argument "<links" sein, und Ihr Markup wird vor den Verweisen behandelt. Die zweite Option ist, die PRR()-Funktion in Ihrer Markup-Definition aufzurufen oder innerhalb Ihrer Markup-Funktion. In dem Falle beginnt PmWiki alle Markups von vorn, wenn Ihre Behandlung abgeschlossen ist.

Wie beginne ich mit dem Schreiben von Rezepten und dem Erzeugen von eigenen Markups?

(alternative) Einführung in angepasste Auszeichnungen für Anfänger

Wie mache ich eine Regel, die einmalig nach der Behandlung aller anderen Regeln angewendet wird?

Wenden Sie diese Anweisung anstelle des üblichen Markup()-Aufrufs an:

$MarkupFrameBase['posteval']['myfooter'] = "\$out = onetimerule(\$out);";

für die Liste aller Seiten


Übersetzung von PmWiki.CustomMarkup,   Originalseite auf PmWikiDe.CustomMarkup   —   Rückverweise

Zuletzt geändert:   PmWikiDe.CustomMarkupam 17.06.2017
 PmWiki.CustomMarkupam 15.06.2017