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 dazu die PHP Funktion "preg_replace" verwendet.

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

Markup($name, $wann, $muster, $ersetzung); # ODER
Markup_e($name, $wann, $muster, $ersetzung);

Wobei mit $name ein eindeutiger Name (Zeichenfolge) für die Regel festgelegt wird. $wann legt fest, wann die Regel im Vergleich zu den Anderen ausgeführt werden soll. $muster enthält das Suchmuster, nach dem im Wikitext gesucht wird und $ersetzung ist die Zeichenkette, die das gesuchte Muster ersetzen soll.

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>.

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 erledigt den Übersetzungsvorgang in mehreren Phasen:

_begin      Beginn der Umwandlung
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.

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 besondere 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".)

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. Bereich innerhalb des geklammerten 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.

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.

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.

Die Option 'e' beim Parameter $muster veranlasst PmWiki, den Parameter $ersetzung nicht als Ersetzungstext, sondern als PHP Ausdruck zu interpretieren, der den Ersetzungsausdruck zurückliefert.

Markup('random', 'directives',
  '/\\(:random:\\)/e',
  "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 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+):\\)/e',
  "rand('$1', '$2')");

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

Beachten Sie: Seien Sie sehr vorsichtig mit dem /e-Modifier in regulären Ausdrücken; arglistige Autoren könnten in der Lage sein, 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 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-Modifier 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. Der existierende Weg funktioniert noch, aber unter PHP 5.5 löst er Warnungen wegen veralteter Features aus.
  • Markup_e($name, $wann, $muster, $ersetzung);
    • $muster darf keinen /e-Modifier enthalten
    • $ersetzung kann eine Zeichenkette mit auszuwertendem Programmkode sein; beachten Sie, dass auf die Übereinstimmungen mit $m[1], $m[2] anstelle von '$1' , '$2' zugegriffen wird.
    • $ersetzung kann der Name einer Funktion sein (callback), die mit dem Array der Übereinstimmungen als Argument aufgerufen wird (PmWiki 2.2.59+).

Beispiele:

  • Für PHP 5.4 und älter ist dies akzeptabel:
    Markup('randomargs', 'directives',
      '/\\(:random (\\d+) (\\d+):\\)/e',
      "rand('$1', '$2')"
      );
  • Für PHP 5.5 und jünger, $ersetzung ist Kode, wir rufen markup_e() auf:
    Markup_e('randomargs', 'directives',
      '/\\(:random (\\d+) (\\d+):\\)/',
      "rand(\$m[1], \$m[2])"
      );
    Das Array $m enthält die Übereinstimmungen in den Klammern des Musters. Die Übereinstimmungen \$m[1] haben einen Backslash vor dem $-Zeichen, damit die Variable in den doppelten Anführungszeichen nicht interpretiert wird. Das läuft auch unter PHP 5.4 und älter, erfordert aber PmWiki 2.2.58 oder jünger.
  • Für PHP5.5 und jünger, $ersetzung ist callback, 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, erfordert aber PmWiki 2.2.58 oder jünger.

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 Programmkode, wir rufen Markup_e() auf:
    Markup_e('Maxi:','<links',
      "/\\b([Mm]axi:)([^\\s\"\\|\\[\\]]+)(\"([^\"]*)\")?/",
      "Keep(LinkMaxi(\$pagename,\$m[1],\$m[2],\$m[4],\$m[1].\$m[2]),'L')"
    );
    
    Die '$1$2'-Zeichenkette in der alten Version wird ersetzt durch \$m[1].\$m[2], zwei aneinandergehängte Elemente des Arrays mit Übereinstimmungen. Das läuft auch unter PHP 5.4 und älter, erfordert aber PmWiki 2.2.58 oder jünger.
  • $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');
    }
    

Offensichtlich kann die LinkMaxi-Funktion auch umgeschrieben werden, sodass sie das Übereinstimmungs-Array direkt akzeptiert. Das läuft auch unter PHP 5.4 und älter, erfordert aber PmWiki 2.2.58 oder jünger.

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; # or return Keep($html);
}

Markup für beide, neue und alte, Versionen von PmWiki

Wenn Ihr Rezept mit PmWiki 2.2.58 und jünger unter PHP 5.5 und mit älteren PmWiki+PHP-Versionen laufen soll, können Sie etwa das Folgende benutzen:

if(function_exists('Markup_e')) { # new format, no /e
  Markup_e('rnd', 'directives', '/\\(:random (\\d+) (\\d+):\\)/', "rand(\$m[1], \$m[2])");
}
else { # old format
  Markup('rnd', 'directives', '/\\(:random (\\d+) (\\d+):\\)/e', "rand($1, $2)");
}

Wenn Sie Fragen bezüglich des neuen Weges haben, 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:\\)/e', 'setHideDiscussion(true)'); 
function setHideDiscussion($val) { 
  global $HideDiscussion; 
  $HideDiscussion = $val;
} 

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.

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 11.06.2016
 PmWiki.CustomMarkupam 05.09.2016