Rewrite the parser in a more friendly and accessible implementation...
authorHappy-melon <happy-melon@users.mediawiki.org>
Thu, 1 Apr 2010 10:50:43 +0000 (10:50 +0000)
committerHappy-melon <happy-melon@users.mediawiki.org>
Thu, 1 Apr 2010 10:50:43 +0000 (10:50 +0000)
includes/AutoLoader.php
includes/parser/LOLParser.php [new file with mode: 0644]
includes/parser/Parser.lol [new file with mode: 0644]

index 54180d3..be1ff10 100644 (file)
@@ -463,7 +463,7 @@ $wgAutoloadLocalClasses = array(
        'PPNode_Hash_Tree' => 'includes/parser/Preprocessor_Hash.php',
        'PPTemplateFrame_DOM' => 'includes/parser/Preprocessor_DOM.php',
        'PPTemplateFrame_Hash' => 'includes/parser/Preprocessor_Hash.php',
-       'Parser' => 'includes/parser/Parser.php',
+       'Parser' => 'includes/parser/LOLParser.php',
        'ParserCache' => 'includes/parser/ParserCache.php',
        'ParserOptions' => 'includes/parser/ParserOptions.php',
        'ParserOutput' => 'includes/parser/ParserOutput.php',
@@ -684,7 +684,7 @@ function wfLoadAllExtensions() {
        AutoLoader::loadAllExtensions();
 }
 
-if ( function_exists( 'spl_autoload_register' ) ) {
+if ( function_exists( 'spl_autoload_register' ) && false ) {
        spl_autoload_register( array( 'AutoLoader', 'autoload' ) );
 } else {
        function __autoload( $class ) {
diff --git a/includes/parser/LOLParser.php b/includes/parser/LOLParser.php
new file mode 100644 (file)
index 0000000..8f6d8c4
--- /dev/null
@@ -0,0 +1,170 @@
+<?php
+/*
+ * lol_core.php Ver 0.3
+ * Copyright (c) 2007 Jeff Jones, www.tetraboy.com, 2010 Happy-melon
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+function lol_core_parse( $code ) {
+       return lol_core_replace( $code, 'forwards' );
+}
+function lol_core_unparse( $code ) {
+       return lol_core_replace( $code, 'backwards' );
+}
+
+define( 'LOL_ANY', '(.+?)' );
+define( 'LOL_LABEL', '([a-zA-Z0-9_-]+)' );
+define( 'LOL_VAR', '\$([a-zA-Z0-9_-]+)' );
+define( 'LOL_FNAME', '([a-zA-Z0-9_\-\>]+)' );
+define( 'LOL_MNAME', '\$this\-\>([a-zA-Z0-9_\-\>]+)' );
+define( 'LOL_VARLIST', '((?:'.LOL_VAR.'(?:,\s*)?)+)' );
+define( 'LOL_CMT', '((\/\/|#) (.*))?');
+function lol_core_replace($code, $dir ) {
+       $backwards = array(
+               '/^([\s]*)'.LOL_VAR.'( = null)?;/', '$1 I HAS $2',
+               '/^([\s]*)var '.LOL_VARLIST.';/', '$1 I HAS UR $2',
+               '/^([\s]*)global '.LOL_VARLIST.';/', '$1 I HAS UR $2 ON UR INTERNETS',
+               '/^([\s]*)'.LOL_VAR.' += array\(\);/', '$1 I HAS $2 IZ EMPTY',
+               '/^([\s]*)'.LOL_VAR.' += array\(/', '$1 I HAS $2 IZ BUCKET',
+               '/^([\s]*)'.LOL_VAR.' += (.+);/', '$1 I HAS $2 IZ $3',
+               '/^([\s]*)'.LOL_VAR.'++;/', '$1 $2 UPUP!',
+               '/^([\s]*)'.LOL_VAR.' = '.LOL_FNAME.'\( (.+) \);/', '$1 $2 IZ ON UR $3 DOING $4',
+               '/^([\s]*)'.LOL_MNAME.'\(\);/', '$1 IM ON UR SPECIAL $2',
+               '/^([\s]*)'.LOL_MNAME.'\( (.+) \);/', '$1 IM ON UR SPECIAL $2 DOING $3',
+               '/^([\s]*)'.LOL_FNAME.'\(\);/', '$1 IM ON UR $2',
+               '/^([\s]*)'.LOL_FNAME.'\( (.+) \);/', '$1 IM ON UR $2 DOING $3',
+       
+               '/^([\s]*)class '.LOL_FNAME.' {/', '$1 IM IN UR SPECIAL $2',
+               '/^([\s]*)const '.LOL_FNAME.' = (.+)/', '$1 I ALWAYZ HAS $2 IZ $3',
+               '/^([\s]*)foreach \( '.LOL_VAR.' as \$(.+) \) {/', '$1 IM IN UR $2 ITZA $3',
+               '/^([\s]*)while \( (.+) \) {/', '$1 STEALIN UR $2',
+       
+               '/^([\s]*)return (.*);/', '$1 I FOUND MAH $2',
+       
+               '/^([\s]*)'.LOL_VAR.' = (.*)/', '$1 $2 IZ $3',
+               '/^([\s]*)'.LOL_VAR.' \.= (.*)/', '$1 $2 HAS MOAR $3',
+               '/^([\s]*)'.LOL_MNAME.' = array\(\)/', '$1 UR SPECIAL $2 IZ EMPTY',
+               '/^([\s]*)'.LOL_MNAME.' = array\(/', '$1 UR SPECIAL $2 IZ BUCKET',
+               '/^([\s]*)'.LOL_MNAME.' = (.*)/', '$1 UR SPECIAL $2 IZ $3',
+       
+               '/^([\s]*)(?:private |protected |public )?function '.LOL_FNAME.' ?\(\) \{ (.+) \}/', '$1 SO IM LIKE $2 TESTING UR $3',
+               '/^([\s]*)(?:private |protected |public )?function '.LOL_FNAME.' ?\( (.*) \) \{ (.+) \}/', '$1 SO IM LIKE $2 WITH UR $3 TESTING UR $4',
+               '/^([\s]*)(?:private |protected |public )?function '.LOL_FNAME.' ?\( (.*) \) \{/', '$1 SO IM LIKE $2 WITH UR $3',
+               '/^([\s]*)(?:private |protected |public )?function '.LOL_FNAME.' ?\(\) \{/', '$1 SO IM LIKE $2',
+               '/^([\s]*)(?:private |protected |public )?static function '.LOL_FNAME.' ?\(\) \{/', '$1 SO IM ALWAYS LIKE $2',
+               '/^([\s]*)(?:private |protected |public )?static function '.LOL_FNAME.' ?\( (.*) \) \{/', '$1 SO IM ALWAYS LIKE $2 WITH UR $3',
+       
+               '/^([\s]*)if \( (.+) \) \{/', '$1 IZ $2',
+               '/^([\s]*)\} elseif \( (.+) \) \{/', '$1 ORLY $2',
+               '/^([\s]*)\} else \{/', '$1 NOWAI',
+       
+               '/^([\s]*)(\/\/|\#) (.*)/', '$1 BTW $3',
+               '/^([\s]*)\/\*\*?/', '$1 DO NOT WANT',
+               '/^([\s]*)\*\//', '$1 WANT',
+               '/^([\s]*)\* ?(.*)/', '$1 NOT WANT $2',
+       
+               '/^([\s]*)\);/', '$1 BUCKET',
+               '/^([\s]*)\}/', '$1 KTHX',
+       );
+       
+       $forwards = array(
+               '/^([\s]*) I HAS UR '.LOL_VARLIST.' ON UR INTERNETS[\s]+/', '$1 global $2;',
+               '/^([\s]*) I HAS UR '.LOL_VARLIST.'[\s]+/', '$1 var $2;',
+               '/^([\s]*) I HAS '.LOL_LABEL.' IZ BUCKET[\s]+/', '$1\$$2 = array(',
+               '/^([\s]*) I HAS '.LOL_LABEL.' IZ EMPTY[\s]+/', '$1 \$$2 = array();',
+               '/^([\s]*) I HAS '.LOL_LABEL.' IZ '.LOL_ANY.''.LOL_CMT.'[\s]+$/', '$1 \$$2 = $3; $4',
+               '/^([\s]*) I HAS '.LOL_LABEL.'[\s]+/', '$1 \$$2;',
+               '/^([\s]*) '.LOL_LABEL.' IZ ON UR '.LOL_FNAME.' DOING '.LOL_ANY.''.LOL_CMT.'[\s]+$/', '$1 \$$2 = $3( $4 ); $5',
+               '/^([\s]*) IM ON UR SPECIAL '.LOL_FNAME.' DOING '.LOL_ANY.''.LOL_CMT.'[\s]*$/', '$1 \$this->$2( $3 ); $4',
+               '/^([\s]*) IM ON UR SPECIAL '.LOL_FNAME.'[\s]*/', '$1 \$this->$2();',
+               '/^([\s]*) IM ON UR '.LOL_FNAME.' DOING(.+)'.LOL_CMT.'[\s]+/', '$1 $2( $3 ); $4',
+               '/^([\s]*) IM ON UR '.LOL_FNAME.'[\s]+/', '$1 $2();',
+               '/^([\s]*) '.LOL_LABEL.' UPUP[\s]+/', '$1 $2++',
+       
+               '/^([\s]*) IM IN UR SPECIAL '.LOL_FNAME.'[\s]+/', '$1 class $2 {',
+               '/^([\s]*) I ALWAYZ HAS '.LOL_FNAME.' IZ (.+)[\s]+/', '$1 const $2 = $3',
+               '/^([\s]*) IM IN UR '.LOL_LABEL.' ITZA (.+)[\s]+/', '$1 foreach ( \$$2 as \$$3 ) {',
+               '/^([\s]*) STEALIN UR (.+)[\s]+/', '$1 while( $2 ) {',
+       
+               '/^([\s]*) I FOUND MAH (.*)[\s]+/', '$1 return $2;',
+       
+               '/^([\s]*) UR SPECIAL '.LOL_FNAME.' IZ EMPTY[\s]*/', '$1 \$this->$2 = array()',
+               '/^([\s]*) UR SPECIAL '.LOL_FNAME.' IZ BUCKET[\s]+/', '$1 \$this->$2 = array(',
+               '/^([\s]*) UR SPECIAL '.LOL_FNAME.' IZ '.LOL_ANY.''.LOL_CMT.'[\s]*$/', '$1 \$this->$2 = $3 $4',
+               '/^([\s]*)'.LOL_LABEL.' IZ (.*)[\s]+/', '$1 \$$2 = $3',
+               '/^([\s]*)'.LOL_LABEL.' HAS MOAR (.*)[\s]+/', '$1 \$$2 .= $3',
+       
+               '/^([\s]*) SO IM LIKE '.LOL_FNAME.' TESTING UR (.+)[\s]+/', '$1 function $2(){ $3 }',
+               '/^([\s]*) SO IM LIKE '.LOL_FNAME.' WITH UR (.*) TESTING UR (.+)[\s]+/', '$1 function $2( $3 ) { $4 }',
+               '/^([\s]*) SO IM LIKE '.LOL_FNAME.' WITH UR (.*)[\s]+/', '$1 function $2( $3 ) {',
+               '/^([\s]*) SO IM LIKE '.LOL_FNAME.'[\s]+/', '$1 function $2(){',
+               '/^([\s]*) SO IM ALWAYS LIKE '.LOL_FNAME.' WITH UR (.*)[\s]+/', '$1 static function $2( $3 ) {',
+               '/^([\s]*) SO IM ALWAYS LIKE '.LOL_FNAME.'[\s]+/', '$1 static function $2(){',
+       
+               '/^([\s]*) IZ '.LOL_ANY.''.LOL_CMT.'[\s]+$/', '$1 if( $2 ) { $3',
+               '/^([\s]*) ORLY '.LOL_ANY.''.LOL_CMT.'[\s]+$/', '$1 } elseif( $2 ) { $3',
+               '/^([\s]*) NOWAI[\s]+/', '$1 } else {',
+       
+               '/^([\s]*) BTW (.*)[\s]*/', '$1 # $2',
+               '/^([\s]*) DO NOT WANT[\s]*/', '$1 /**',
+               '/^([\s]*) WANT[\s]*/', '$1 */',
+               '/^([\s]*) NOT WANT (.*)[\s]*/', '$1 * $2',
+       
+               '/^([\s]*) BUCKET[\s]*/', '$1 );',
+               '/^([\s]*) KTHX[\s]*/', '$1 }',
+       );
+       
+       $code = is_array( $code )
+               ? $code
+               : explode("\n",$code);
+
+       $search = array();
+       $replace = array();
+       foreach( $$dir as $key => $var ){
+               if( 1 & $key )  {
+                       $replace[] = $var;
+               } else {
+                       $search[] = $var;
+               }
+       }
+       
+       $code = preg_replace( $search, $replace, $code );
+       $code = implode( "\n", $code );
+       return $code;
+}
+
+
+
+## Parser implementation ##
+if( false ){ # set to false to disable
+       $lol = file( dirname(__FILE__).'/Parser.lol', FILE_IGNORE_NEW_LINES );
+       $php = lol_core_parse( $lol );
+       try { 
+               eval( $php );
+       } catch ( Exception $e ){
+               require_once( 'Parser.php' );
+       }
+} else {
+       # You're no fun... 
+       require_once( 'Parser.php' );
+}
+
+
+
+
diff --git a/includes/parser/Parser.lol b/includes/parser/Parser.lol
new file mode 100644 (file)
index 0000000..fc89f29
--- /dev/null
@@ -0,0 +1,5282 @@
+ DO NOT WANT\r
+  NOT WANT @defgroup Parser Parser\r
+  NOT WANT \r
+  NOT WANT @file\r
+  NOT WANT @ingroup Parser\r
+  NOT WANT File for Parser and related classes\r
+  WANT\r
+\r
+\r
+ DO NOT WANT\r
+  NOT WANT PHP Parser - Processes wiki markup (which uses a more user-friendly\r
+  NOT WANT syntax, such as "[[link]]" for making links), and provides a one-way\r
+  NOT WANT transformation of that wiki markup it into XHTML output / markup\r
+  NOT WANT (which in turn the browser understands, and can display).\r
+  NOT WANT \r
+  NOT WANT <pre>\r
+  NOT WANT There are five main entry points into the Parser class:\r
+  NOT WANT parse()\r
+  NOT WANT     produces HTML output\r
+  NOT WANT preSaveTransform().\r
+  NOT WANT     produces altered wiki markup.\r
+  NOT WANT preprocess()\r
+  NOT WANT     removes HTML comments and expands templates\r
+  NOT WANT cleanSig()\r
+  NOT WANT     Cleans a signature before saving it to preferences\r
+  NOT WANT extractSections()\r
+  NOT WANT     Extracts sections from an article for section editing\r
+  NOT WANT getPreloadText()\r
+  NOT WANT     Removes <noinclude> sections, and <includeonly> tags.\r
+  NOT WANT \r
+  NOT WANT Globals used:\r
+  NOT WANT    objects:   $wgLang, $wgContLang\r
+  NOT WANT \r
+  NOT WANT NOT $wgArticle, $wgUser or $wgTitle. Keep them away!\r
+  NOT WANT \r
+  NOT WANT settings:\r
+  NOT WANT  $wgUseTex*, $wgUseDynamicDates*, $wgInterwikiMagic*,\r
+  NOT WANT  $wgNamespacesWithSubpages, $wgAllowExternalImages*,\r
+  NOT WANT  $wgLocaltimezone, $wgAllowSpecialInclusion*,\r
+  NOT WANT  $wgMaxArticleSize*\r
+  NOT WANT \r
+  NOT WANT  * only within ParserOptions\r
+  NOT WANT </pre>\r
+  NOT WANT \r
+  NOT WANT @ingroup Parser\r
+  WANT\r
+ IM IN UR SPECIAL Parser\r
+        DO NOT WANT\r
+         NOT WANT Update this version number when the ParserOutput format\r
+         NOT WANT changes in an incompatible way, so the parser cache\r
+         NOT WANT can automatically discard old data.\r
+         WANT\r
+        I ALWAYZ HAS VERSION IZ '1.6.4';\r
+\r
+        BTW Flags for Parser::setFunctionHook\r
+        BTW Also available as global constants from Defines.php\r
+        I ALWAYZ HAS SFH_NO_HASH IZ 1;\r
+        I ALWAYZ HAS SFH_OBJECT_ARGS IZ 2;\r
+\r
+        BTW Constants needed for external link processing\r
+        BTW Everything except bracket, space, or control characters\r
+        I ALWAYZ HAS EXT_LINK_URL_CLASS IZ '[^][<>"\\x00-\\x20\\x7F]';\r
+        I ALWAYZ HAS EXT_IMAGE_REGEX IZ '/^(http:\/\/|https:\/\/)([^][<>"\\x00-\\x20\\x7F]+)\r
+               \\/([A-Za-z0-9_.,~%\\-+&;#*?!=()@\\x80-\\xFF]+)\\.((?i)gif|png|jpg|jpeg)$/Sx';\r
+\r
+        BTW State constants for the definition list colon extraction\r
+        I ALWAYZ HAS COLON_STATE_TEXT IZ 0;\r
+        I ALWAYZ HAS COLON_STATE_TAG IZ 1;\r
+        I ALWAYZ HAS COLON_STATE_TAGSTART IZ 2;\r
+        I ALWAYZ HAS COLON_STATE_CLOSETAG IZ 3;\r
+        I ALWAYZ HAS COLON_STATE_TAGSLASH IZ 4;\r
+        I ALWAYZ HAS COLON_STATE_COMMENT IZ 5;\r
+        I ALWAYZ HAS COLON_STATE_COMMENTDASH IZ 6;\r
+        I ALWAYZ HAS COLON_STATE_COMMENTDASHDASH IZ 7;\r
+\r
+        BTW Flags for preprocessToDom\r
+        I ALWAYZ HAS PTD_FOR_INCLUSION IZ 1;\r
+\r
+        BTW Allowed values for $this->mOutputType\r
+        BTW Parameter to startExternalParse().\r
+        I ALWAYZ HAS OT_HTML IZ 1; # like parse()\r
+        I ALWAYZ HAS OT_WIKI IZ 2; # like preSaveTransform()\r
+        I ALWAYZ HAS OT_PREPROCESS IZ 3; # like preprocess()\r
+        I ALWAYZ HAS OT_MSG IZ 3;\r
+        I ALWAYZ HAS OT_PLAIN IZ 4; # like extractSections() - portions of the original are returned unchanged.\r
+\r
+        BTW Marker Suffix needs to be accessible staticly.\r
+        I ALWAYZ HAS MARKER_SUFFIX IZ "-QINU\x7f";\r
+\r
+        BTW Persistent:\r
+        I HAS UR $mTagHooks, $mTransparentTagHooks, $mFunctionHooks, $mFunctionSynonyms, $mVariables\r
+        I HAS UR $mSubstWords, $mImageParams, $mImageParamsMagicArray, $mStripList, $mMarkerIndex\r
+        I HAS UR $mPreprocessor, $mExtLinkBracketedRegex, $mUrlProtocols, $mDefaultStripList\r
+        I HAS UR $mVarCache, $mConf, $mFunctionTagHooks\r
+\r
+\r
+        BTW Cleared with clearState():\r
+        I HAS UR $mOutput, $mAutonumber, $mDTopen, $mStripState\r
+        I HAS UR $mIncludeCount, $mArgStack, $mLastSection, $mInPre\r
+        I HAS UR $mLinkHolders, $mLinkID\r
+        I HAS UR $mIncludeSizes, $mPPNodeCount, $mDefaultSort\r
+        I HAS UR $mTplExpandCache # empty-frame expansion cache\r
+        I HAS UR $mTplRedirCache, $mTplDomCache, $mHeadings, $mDoubleUnderscores\r
+        I HAS UR $mExpensiveFunctionCount # number of expensive parser function calls\r
+\r
+        BTW Temporary\r
+        BTW These are variables reset at least once per parse regardless of $clearState\r
+        I HAS UR $mOptions      # ParserOptions object\r
+        I HAS UR $mTitle        # Title context, used for self-link rendering and similar things\r
+        I HAS UR $mOutputType   # Output type, one of the OT_xxx constants\r
+        I HAS UR $ot            # Shortcut alias, see setOutputType()\r
+        I HAS UR $mRevisionId   # ID to display in {{REVISIONID}} tags\r
+        I HAS UR $mRevisionTimestamp # The timestamp of the specified revision ID\r
+        I HAS UR $mRevIdForTs   # The revision ID which was used to fetch the timestamp\r
+\r
+        DO NOT WANT\r
+         NOT WANT Constructor\r
+         NOT WANT \r
+         NOT WANT @public\r
+         WANT\r
+        SO IM LIKE __construct WITH UR $conf = array()\r
+                UR SPECIAL mConf IZ $conf;\r
+                UR SPECIAL mTagHooks IZ EMPTY;\r
+                UR SPECIAL mTransparentTagHooks IZ EMPTY;\r
+                UR SPECIAL mFunctionHooks IZ EMPTY;\r
+                UR SPECIAL mFunctionTagHooks IZ EMPTY;\r
+                UR SPECIAL mFunctionSynonyms IZ BUCKET 0 => array(), 1 => array() );\r
+                UR SPECIAL mDefaultStripList IZ $this->mStripList = array();\r
+                UR SPECIAL mUrlProtocols IZ wfUrlProtocols();\r
+                UR SPECIAL mExtLinkBracketedRegex IZ '/\[(\b(' . wfUrlProtocols() . ')'.\r
+                       '[^][<>"\\x00-\\x20\\x7F]+) *([^\]\\x0a\\x0d]*?)\]/S';\r
+                UR SPECIAL mVarCache IZ EMPTY;\r
+                IZ isset( $conf['preprocessorClass'] )\r
+                        UR SPECIAL mPreprocessorClass IZ $conf['preprocessorClass'];\r
+                ORLY extension_loaded( 'domxml' )\r
+                        BTW PECL extension that conflicts with the core DOM extension (bug 13770)\r
+                        IM ON UR wfDebug DOING "Warning: you have the obsolete domxml extension for PHP. Please remove it!\n"\r
+                        UR SPECIAL mPreprocessorClass IZ 'Preprocessor_Hash';\r
+                ORLY extension_loaded( 'dom' )\r
+                        UR SPECIAL mPreprocessorClass IZ 'Preprocessor_DOM';\r
+                NOWAI\r
+                        UR SPECIAL mPreprocessorClass IZ 'Preprocessor_Hash';\r
+                KTHX\r
+                UR SPECIAL mMarkerIndex IZ 0;\r
+                UR SPECIAL mFirstCall IZ true;\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Reduce memory usage to reduce the impact of circular references\r
+         WANT\r
+        SO IM LIKE __destruct\r
+                IZ isset( $this->mLinkHolders )\r
+                        IM ON UR SPECIAL mLinkHolders->__destruct\r
+                KTHX\r
+                IM IN UR this ITZA name => $value\r
+                        IM ON UR unset DOING $this->$name\r
+                KTHX\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Do various kinds of initialisation on the first call of the parser\r
+         WANT\r
+        SO IM LIKE firstCallInit\r
+                IZ !$this->mFirstCall\r
+                       return;\r
+                KTHX\r
+                UR SPECIAL mFirstCall IZ false;\r
+\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+\r
+               CoreParserFunctions::register( $this );\r
+               CoreTagHooks::register( $this );\r
+                IM ON UR SPECIAL initialiseVariables\r
+\r
+                IM ON UR wfRunHooks DOING 'ParserFirstCallInit', array( &$this )\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Clear Parser state\r
+         NOT WANT \r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE clearState\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+                IZ $this->mFirstCall\r
+                        IM ON UR SPECIAL firstCallInit\r
+                KTHX\r
+                UR SPECIAL mOutput IZ new ParserOutput;\r
+                UR SPECIAL mAutonumber IZ 0;\r
+                UR SPECIAL mLastSection IZ '';\r
+                UR SPECIAL mDTopen IZ false;\r
+                UR SPECIAL mIncludeCount IZ EMPTY;\r
+                UR SPECIAL mStripState IZ new StripState;\r
+                UR SPECIAL mArgStack IZ false;\r
+                UR SPECIAL mInPre IZ false;\r
+                UR SPECIAL mLinkHolders IZ new LinkHolderArray( $this );\r
+                UR SPECIAL mLinkID IZ 0;\r
+                UR SPECIAL mRevisionTimestamp IZ $this->mRevisionId = null;\r
+                UR SPECIAL mVarCache IZ EMPTY;\r
+\r
+                DO NOT WANT\r
+                 NOT WANT Prefix for temporary replacement strings for the multipass parser.\r
+                 NOT WANT \x07 should never appear in input as it's disallowed in XML.\r
+                 NOT WANT Using it at the front also gives us a little extra robustness\r
+                 NOT WANT since it shouldn't match when butted up against identifier-like\r
+                 NOT WANT string constructs.\r
+                 NOT WANT \r
+                 NOT WANT Must not consist of all title characters, or else it will change\r
+                 NOT WANT the behaviour of <nowiki> in a link.\r
+                 WANT\r
+                BTW $this->mUniqPrefix = "\x07UNIQ" . Parser::getRandomString();\r
+                BTW Changed to \x7f to allow XML double-parsing -- TS\r
+                UR SPECIAL mUniqPrefix IZ "\x7fUNIQ" . self::getRandomString();\r
+\r
+\r
+                BTW Clear these on every parse, bug 4549\r
+                UR SPECIAL mTplExpandCache IZ $this->mTplRedirCache = $this->mTplDomCache = array();\r
+\r
+                UR SPECIAL mShowToc IZ true;\r
+                UR SPECIAL mForceTocPosition IZ false;\r
+                UR SPECIAL mIncludeSizes IZ BUCKET\r
+                       'post-expand' => 0,\r
+                       'arg' => 0,\r
+                BUCKET\r
+                UR SPECIAL mPPNodeCount IZ 0;\r
+                UR SPECIAL mDefaultSort IZ false;\r
+                UR SPECIAL mHeadings IZ EMPTY;\r
+                UR SPECIAL mDoubleUnderscores IZ EMPTY;\r
+                UR SPECIAL mExpensiveFunctionCount IZ 0;\r
+\r
+                BTW Fix cloning\r
+                IZ isset( $this->mPreprocessor ) && $this->mPreprocessor->parser !== $this\r
+                        UR SPECIAL mPreprocessor IZ null;\r
+                KTHX\r
+\r
+                IM ON UR wfRunHooks DOING 'ParserClearState', array( &$this )\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+        KTHX\r
+\r
+        SO IM LIKE setOutputType WITH UR $ot\r
+                UR SPECIAL mOutputType IZ $ot;\r
+                BTW Shortcut alias\r
+                UR SPECIAL ot IZ BUCKET\r
+                       'html' => $ot == self::OT_HTML,\r
+                       'wiki' => $ot == self::OT_WIKI,\r
+                       'pre' => $ot == self::OT_PREPROCESS,\r
+                       'plain' => $ot == self::OT_PLAIN,\r
+                BUCKET\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Set the context title\r
+         WANT\r
+        SO IM LIKE setTitle WITH UR $t\r
+                IZ !$t || $t instanceof FakeTitle\r
+                        I HAS t IZ Title::newFromText( 'NO TITLE' )\r
+                KTHX\r
+\r
+                IZ strval( $t->getFragment() ) !== ''\r
+                        BTW Strip the fragment to avoid various odd effects\r
+                        UR SPECIAL mTitle IZ clone $t;\r
+                        IM ON UR SPECIAL mTitle->setFragment DOING ''\r
+                NOWAI\r
+                        UR SPECIAL mTitle IZ $t;\r
+                KTHX\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Accessor for mUniqPrefix.\r
+         NOT WANT \r
+         NOT WANT @public\r
+         WANT\r
+        SO IM LIKE uniqPrefix\r
+                IZ !isset( $this->mUniqPrefix )\r
+                        BTW @todo Fixme: this is probably *horribly wrong*\r
+                        BTW LanguageConverter seems to want $wgParser's uniqPrefix, however\r
+                        BTW if this is called for a parser cache hit, the parser may not\r
+                        BTW have ever been initialized in the first place.\r
+                        BTW Not really sure what the heck is supposed to be going on here.\r
+                        I FOUND MAH ''\r
+                        BTW throw new MWException( "Accessing uninitialized mUniqPrefix" );\r
+                KTHX\r
+                I FOUND MAH $this->mUniqPrefix\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Convert wikitext to HTML\r
+         NOT WANT Do not call this function recursively.\r
+         NOT WANT \r
+         NOT WANT @param $text String: text we want to parse\r
+         NOT WANT @param $title A title object\r
+         NOT WANT @param $options ParserOptions\r
+         NOT WANT @param $linestart boolean\r
+         NOT WANT @param $clearState boolean\r
+         NOT WANT @param $revid Int: number to pass in {{REVISIONID}}\r
+         NOT WANT @return ParserOutput a ParserOutput\r
+         WANT\r
+        SO IM LIKE parse WITH UR $text, Title $title, ParserOptions $options, $linestart = true, $clearState = true, $revid = null\r
+                DO NOT WANT\r
+                 NOT WANT First pass--just handle <nowiki> sections, pass the rest off\r
+                 NOT WANT to internalParse() which does all the real work.\r
+                 WANT\r
+\r
+                I HAS UR $wgUseTidy, $wgAlwaysUseTidy, $wgContLang, $wgDisableLangConversion ON UR INTERNETS\r
+                I HAS fname IZ __METHOD__.'-' . wfGetCaller()\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+                IM ON UR wfProfileIn DOING $fname\r
+\r
+                IZ $clearState\r
+                        IM ON UR SPECIAL clearState\r
+                KTHX\r
+\r
+                UR SPECIAL mOptions IZ $options;\r
+                IM ON UR SPECIAL setTitle DOING $title # Page title has to be set for the pre-processor\r
+\r
+                I HAS oldRevisionId IZ $this->mRevisionId\r
+                I HAS oldRevisionTimestamp IZ $this->mRevisionTimestamp\r
+                IZ $revid !== null\r
+                        UR SPECIAL mRevisionId IZ $revid;\r
+                        UR SPECIAL mRevisionTimestamp IZ null;\r
+                KTHX\r
+                IM ON UR SPECIAL setOutputType DOING self::OT_HTML\r
+                IM ON UR wfRunHooks DOING 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState )\r
+                BTW No more strip!\r
+                IM ON UR wfRunHooks DOING 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState )\r
+                I HAS text IZ $this->internalParse( $text )\r
+\r
+                I HAS text IZ $this->mStripState->unstripGeneral( $text )\r
+\r
+                BTW Clean up special characters, only run once, next-to-last before doBlockLevels\r
+                I HAS fixtags IZ BUCKET\r
+                        BTW french spaces, last one Guillemet-left\r
+                        BTW only if there is something before the space\r
+                       '/(.) (?=\\?|:|;|!|%|\\302\\273)/' => '\\1&nbsp;\\2',\r
+                        BTW french spaces, Guillemet-right\r
+                       '/(\\302\\253) /' => '\\1&nbsp;',\r
+                       '/&nbsp;(!\s*important)/' => ' \\1', # Beware of CSS magic word !important, bug #11874.\r
+                BUCKET\r
+                I HAS text IZ preg_replace( array_keys( $fixtags ), array_values( $fixtags ), $text )\r
+\r
+                I HAS text IZ $this->doBlockLevels( $text, $linestart )\r
+\r
+                IM ON UR SPECIAL replaceLinkHolders DOING $text\r
+\r
+                BTW The position of the convert() call should not be changed. it\r
+                BTW assumes that the links are all replaced and the only thing left\r
+                BTW is the <nowiki> mark.\r
+               if ( !( $wgDisableLangConversion\r
+                               || isset( $this->mDoubleUnderscores['nocontentconvert'] )\r
+                               || $this->mTitle->isTalkPage()\r
+                               || $this->mTitle->isConversionTable() ) ) {\r
+                        I HAS text IZ $wgContLang->convert( $text )\r
+                KTHX\r
+\r
+                BTW A title may have been set in a conversion rule.\r
+                BTW Note that if a user tries to set a title in a conversion\r
+                BTW rule but content conversion was not done, then the parser\r
+                BTW won't pick it up.  This is probably expected behavior.\r
+                IZ $wgContLang->getConvRuleTitle()\r
+                        IM ON UR SPECIAL mOutput->setTitleText DOING $wgContLang->getConvRuleTitle()\r
+                KTHX\r
+\r
+                I HAS text IZ $this->mStripState->unstripNoWiki( $text )\r
+\r
+                IM ON UR wfRunHooks DOING 'ParserBeforeTidy', array( &$this, &$text )\r
+\r
+//!JF Move to its own function\r
+\r
+                I HAS uniq_prefix IZ $this->mUniqPrefix\r
+                I HAS matches IZ EMPTY\r
+                I HAS elements IZ array_keys( $this->mTransparentTagHooks )\r
+                I HAS text IZ self::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix )\r
+\r
+                IM IN UR matches ITZA marker => $data\r
+                       list( $element, $content, $params, $tag ) = $data;\r
+                        I HAS tagName IZ strtolower( $element )\r
+                        IZ isset( $this->mTransparentTagHooks[$tagName] )\r
+                                I HAS output IZ call_user_func_array( $this->mTransparentTagHooks[$tagName], array( $content, $params, $this ) )\r
+                        NOWAI\r
+                                I HAS output IZ $tag\r
+                        KTHX\r
+                        IM ON UR SPECIAL mStripState->general->setPair DOING $marker, $output\r
+                KTHX\r
+                I HAS text IZ $this->mStripState->unstripGeneral( $text )\r
+\r
+                I HAS text IZ Sanitizer::normalizeCharReferences( $text )\r
+\r
+                IZ ( $wgUseTidy && $this->mOptions->mTidy ) || $wgAlwaysUseTidy\r
+                        I HAS text IZ MWTidy::tidy( $text )\r
+                NOWAI\r
+                        BTW attempt to sanitize at least some nesting problems\r
+                        BTW (bug #2702 and quite a few others)\r
+                        I HAS tidyregs IZ BUCKET\r
+                                BTW ''Something [http://www.cool.com cool''] -->\r
+                                BTW <i>Something</i><a href="http://www.cool.com"..><i>cool></i></a>\r
+                               '/(<([bi])>)(<([bi])>)?([^<]*)(<\/?a[^<]*>)([^<]*)(<\/\\4>)?(<\/\\2>)/' =>\r
+                               '\\1\\3\\5\\8\\9\\6\\1\\3\\7\\8\\9',\r
+                                BTW fix up an anchor inside another anchor, only\r
+                                BTW at least for a single single nested link (bug 3695)\r
+                               '/(<a[^>]+>)([^<]*)(<a[^>]+>[^<]*)<\/a>(.*)<\/a>/' =>\r
+                               '\\1\\2</a>\\3</a>\\1\\4</a>',\r
+                                BTW fix div inside inline elements- doBlockLevels won't wrap a line which\r
+                                BTW contains a div, so fix it up here; replace\r
+                                BTW div with escaped text\r
+                               '/(<([aib]) [^>]+>)([^<]*)(<div([^>]*)>)(.*)(<\/div>)([^<]*)(<\/\\2>)/' =>\r
+                               '\\1\\3&lt;div\\5&gt;\\6&lt;/div&gt;\\8\\9',\r
+                                BTW remove empty italic or bold tag pairs, some\r
+                                BTW introduced by rules above\r
+                               '/<([bi])><\/\\1>/' => '',\r
+                        BUCKET\r
+\r
+                        text IZ preg_replace(\r
+                               array_keys( $tidyregs ),\r
+                               array_values( $tidyregs ),\r
+                               $text );\r
+                KTHX\r
+                I HAS UR $wgExpensiveParserFunctionLimit ON UR INTERNETS\r
+                IZ $this->mExpensiveFunctionCount > $wgExpensiveParserFunctionLimit\r
+                        IM ON UR SPECIAL limitationWarn DOING 'expensive-parserfunction', $this->mExpensiveFunctionCount, $wgExpensiveParserFunctionLimit\r
+                KTHX\r
+\r
+                IM ON UR wfRunHooks DOING 'ParserAfterTidy', array( &$this, &$text )\r
+\r
+                BTW Information on include size limits, for the benefit of users who try to skirt them\r
+                IZ $this->mOptions->getEnableLimitReport()\r
+                        I HAS max IZ $this->mOptions->getMaxIncludeSize()\r
+                        I HAS PFreport IZ "Expensive parser function count: {$this->mExpensiveFunctionCount}/$wgExpensiveParserFunctionLimit\n"\r
+                       $limitReport =\r
+                               "NewPP limit report\n" .\r
+                               "Preprocessor node count: {$this->mPPNodeCount}/{$this->mOptions->mMaxPPNodeCount}\n" .\r
+                               "Post-expand include size: {$this->mIncludeSizes['post-expand']}/$max bytes\n" .\r
+                               "Template argument size: {$this->mIncludeSizes['arg']}/$max bytes\n".\r
+                                I HAS PFreport\r
+                        IM ON UR wfRunHooks DOING 'ParserLimitReport', array( $this, &$limitReport )\r
+                        text HAS MOAR "\n<!-- \n$limitReport-->\n";\r
+                KTHX\r
+                IM ON UR SPECIAL mOutput->setText DOING $text\r
+\r
+                UR SPECIAL mRevisionId IZ $oldRevisionId;\r
+                UR SPECIAL mRevisionTimestamp IZ $oldRevisionTimestamp;\r
+                IM ON UR wfProfileOut DOING $fname\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+\r
+                I FOUND MAH $this->mOutput\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Recursive parser entry point that can be called from an extension tag\r
+         NOT WANT hook.\r
+         NOT WANT \r
+         NOT WANT If $frame is not provided, then template variables (e.g., {{{1}}}) within $text are not expanded\r
+         NOT WANT \r
+         NOT WANT @param $text String: text extension wants to have parsed\r
+         NOT WANT @param PPFrame $frame: The frame to use for expanding any template variables\r
+         WANT\r
+        SO IM LIKE recursiveTagParse WITH UR $text, $frame=false\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+                IM ON UR wfRunHooks DOING 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState )\r
+                IM ON UR wfRunHooks DOING 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState )\r
+                I HAS text IZ $this->internalParse( $text, false, $frame )\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Expand templates and variables in the text, producing valid, static wikitext.\r
+         NOT WANT Also removes comments.\r
+         WANT\r
+        SO IM LIKE preprocess WITH UR $text, $title, $options, $revid = null\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+                IM ON UR SPECIAL clearState\r
+                IM ON UR SPECIAL setOutputType DOING self::OT_PREPROCESS\r
+                UR SPECIAL mOptions IZ $options;\r
+                IM ON UR SPECIAL setTitle DOING $title\r
+                IZ $revid !== null\r
+                        UR SPECIAL mRevisionId IZ $revid;\r
+                KTHX\r
+                IM ON UR wfRunHooks DOING 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState )\r
+                IM ON UR wfRunHooks DOING 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState )\r
+                I HAS text IZ $this->replaceVariables( $text )\r
+                I HAS text IZ $this->mStripState->unstripBoth( $text )\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Process the wikitext for the ?preload= feature. (bug 5210)\r
+         NOT WANT \r
+         NOT WANT <noinclude>, <includeonly> etc. are parsed as for template transclusion, \r
+         NOT WANT comments, templates, arguments, tags hooks and parser functions are untouched.\r
+         WANT\r
+        SO IM LIKE getPreloadText WITH UR $text, $title, $options\r
+                BTW Parser (re)initialisation\r
+                IM ON UR SPECIAL clearState\r
+                IM ON UR SPECIAL setOutputType DOING self::OT_PLAIN\r
+                UR SPECIAL mOptions IZ $options;\r
+                IM ON UR SPECIAL setTitle DOING $title \r
+\r
+                I HAS flags IZ PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES\r
+                I HAS dom IZ $this->preprocessToDom( $text, self::PTD_FOR_INCLUSION )\r
+                I FOUND MAH $this->getPreprocessor()->newFrame()->expand( $dom, $flags )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Get a random string\r
+         NOT WANT \r
+         NOT WANT @private\r
+         NOT WANT @static\r
+         WANT\r
+        SO IM LIKE getRandomString\r
+                I FOUND MAH dechex( mt_rand( 0, 0x7fffffff ) ) . dechex( mt_rand( 0, 0x7fffffff ) )\r
+        KTHX\r
+\r
+       function &getTitle() { return $this->mTitle; }\r
+        SO IM LIKE getOptions TESTING UR return $this->mOptions;\r
+        SO IM LIKE getRevisionId TESTING UR return $this->mRevisionId;\r
+        SO IM LIKE getOutput TESTING UR return $this->mOutput;\r
+        SO IM LIKE nextLinkID TESTING UR return $this->mLinkID++;\r
+\r
+        SO IM LIKE getFunctionLang\r
+                I HAS UR $wgLang, $wgContLang ON UR INTERNETS\r
+\r
+                I HAS target IZ $this->mOptions->getTargetLanguage()\r
+                IZ $target !== null\r
+                        I FOUND MAH $target\r
+                NOWAI\r
+                        I FOUND MAH $this->mOptions->getInterfaceMessage() ? $wgLang : $wgContLang\r
+                KTHX\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Get a preprocessor object\r
+         WANT\r
+        SO IM LIKE getPreprocessor\r
+                IZ !isset( $this->mPreprocessor )\r
+                        I HAS class IZ $this->mPreprocessorClass\r
+                        UR SPECIAL mPreprocessor IZ new $class( $this );\r
+                KTHX\r
+                I FOUND MAH $this->mPreprocessor\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Replaces all occurrences of HTML-style comments and the given tags\r
+         NOT WANT in the text with a random marker and returns the next text. The output\r
+         NOT WANT parameter $matches will be an associative array filled with data in\r
+         NOT WANT the form:\r
+         NOT WANT   'UNIQ-xxxxx' => array(\r
+         NOT WANT     'element',\r
+         NOT WANT     'tag content',\r
+         NOT WANT     array( 'param' => 'x' ),\r
+         NOT WANT     '<element param="x">tag content</element>' ) )\r
+         NOT WANT \r
+         NOT WANT @param $elements list of element names. Comments are always extracted.\r
+         NOT WANT @param $text Source text string.\r
+         NOT WANT @param $uniq_prefix\r
+         NOT WANT \r
+         NOT WANT @public\r
+         NOT WANT @static\r
+         WANT\r
+        SO IM LIKE extractTagsAndParams WITH UR $elements, $text, &$matches, $uniq_prefix = ''\r
+               static $n = 1;\r
+                I HAS stripped IZ ''\r
+                I HAS matches IZ EMPTY\r
+\r
+                I HAS taglist IZ implode( '|', $elements )\r
+                I HAS start IZ "/<($taglist)(\\s+[^>]*?|\\s*?)(\/?" . ">)|<(!--)/i"\r
+\r
+                STEALIN UR $text != ''\r
+                        I HAS p IZ preg_split( $start, $text, 2, PREG_SPLIT_DELIM_CAPTURE )\r
+                        stripped HAS MOAR $p[0];\r
+                        IZ count( $p ) < 5\r
+                               break;\r
+                        KTHX\r
+                        IZ count( $p ) > 5\r
+                                BTW comment\r
+                                I HAS element IZ $p[4]\r
+                                I HAS attributes IZ ''\r
+                                I HAS close IZ ''\r
+                                I HAS inside IZ $p[5]\r
+                        NOWAI\r
+                                BTW tag\r
+                                I HAS element IZ $p[1]\r
+                                I HAS attributes IZ $p[2]\r
+                                I HAS close IZ $p[3]\r
+                                I HAS inside IZ $p[4]\r
+                        KTHX\r
+\r
+                        I HAS marker IZ "$uniq_prefix-$element-" . sprintf( '%08X', $n++ ) . self::MARKER_SUFFIX\r
+                        stripped HAS MOAR $marker;\r
+\r
+                        IZ $close === '/>'\r
+                                BTW Empty element tag, <tag />\r
+                                I HAS content\r
+                                I HAS text IZ $inside\r
+                                I HAS tail\r
+                        NOWAI\r
+                                IZ $element === '!--'\r
+                                        I HAS end IZ '/(-->)/'\r
+                                NOWAI\r
+                                        I HAS end IZ "/(<\\/$element\\s*>)/i"\r
+                                KTHX\r
+                                I HAS q IZ preg_split( $end, $inside, 2, PREG_SPLIT_DELIM_CAPTURE )\r
+                                I HAS content IZ $q[0]\r
+                                IZ count( $q ) < 3\r
+                                        BTW No end tag -- let it run out to the end of the text.\r
+                                        I HAS tail IZ ''\r
+                                        I HAS text IZ ''\r
+                                NOWAI\r
+                                        I HAS tail IZ $q[1]\r
+                                        I HAS text IZ $q[2]\r
+                                KTHX\r
+                        KTHX\r
+\r
+                       $matches[$marker] = array( $element,\r
+                               $content,\r
+                               Sanitizer::decodeTagAttributes( $attributes ),\r
+                               "<$element$attributes$close$content$tail" );\r
+                KTHX\r
+                I FOUND MAH $stripped\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Get a list of strippable XML-like elements\r
+         WANT\r
+        SO IM LIKE getStripList\r
+                I FOUND MAH $this->mStripList\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT @deprecated use replaceVariables\r
+         WANT\r
+        SO IM LIKE strip WITH UR $text, $state, $stripcomments = false , $dontstrip = array()\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Restores pre, math, and other extensions removed by strip()\r
+         NOT WANT \r
+         NOT WANT always call unstripNoWiki() after this one\r
+         NOT WANT @private\r
+         NOT WANT @deprecated use $this->mStripState->unstrip()\r
+         WANT\r
+        SO IM LIKE unstrip WITH UR $text, $state\r
+                I FOUND MAH $state->unstripGeneral( $text )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Always call this after unstrip() to preserve the order\r
+         NOT WANT \r
+         NOT WANT @private\r
+         NOT WANT @deprecated use $this->mStripState->unstrip()\r
+         WANT\r
+        SO IM LIKE unstripNoWiki WITH UR $text, $state\r
+                I FOUND MAH $state->unstripNoWiki( $text )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT @deprecated use $this->mStripState->unstripBoth()\r
+         WANT\r
+        SO IM LIKE unstripForHTML WITH UR $text\r
+                I FOUND MAH $this->mStripState->unstripBoth( $text )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Add an item to the strip state\r
+         NOT WANT Returns the unique tag which must be inserted into the stripped text\r
+         NOT WANT The tag will be replaced with the original text in unstrip()\r
+         NOT WANT \r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE insertStripItem WITH UR $text\r
+                I HAS rnd IZ "{$this->mUniqPrefix}-item-{$this->mMarkerIndex}-" . self::MARKER_SUFFIX\r
+               $this->mMarkerIndex++;\r
+                IM ON UR SPECIAL mStripState->general->setPair DOING $rnd, $text\r
+                I FOUND MAH $rnd\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Interface with html tidy\r
+         NOT WANT @deprecated Use MWTidy::tidy()\r
+         WANT\r
+        SO IM ALWAYS LIKE tidy WITH UR $text\r
+                IM ON UR wfDeprecated DOING __METHOD__\r
+                I FOUND MAH MWTidy::tidy( $text )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT parse the wiki syntax used to render tables\r
+         NOT WANT \r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE doTableStuff WITH UR $text\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+\r
+                I HAS lines IZ StringUtils::explode( "\n", $text )\r
+                I HAS out IZ ''\r
+                I HAS td_history IZ EMPTY # Is currently a td tag open?\r
+                I HAS last_tag_history IZ EMPTY # Save history of last lag activated (td, th or caption)\r
+                I HAS tr_history IZ EMPTY # Is currently a tr tag open?\r
+                I HAS tr_attributes IZ EMPTY # history of tr attributes\r
+                I HAS has_opened_tr IZ EMPTY # Did this table open a <tr> element?\r
+                I HAS indent_level IZ 0 # indent level of the table\r
+\r
+                IM IN UR lines ITZA outLine\r
+                        I HAS line IZ trim( $outLine )\r
+\r
+                        IZ $line == '' # empty line, go to next line\r
+                                out HAS MOAR $outLine."\n";\r
+                               continue;\r
+                        KTHX\r
+                        I HAS first_character IZ $line[0]\r
+                        I HAS matches IZ EMPTY\r
+\r
+                        IZ preg_match( '/^(:*)\{\|(.*)$/', $line , $matches )\r
+                                BTW First check if we are starting a new table\r
+                                I HAS indent_level IZ strlen( $matches[1] )\r
+\r
+                                I HAS attributes IZ $this->mStripState->unstripBoth( $matches[2] )\r
+                                I HAS attributes IZ Sanitizer::fixTagAttributes( $attributes , 'table' )\r
+\r
+                                I HAS outLine IZ str_repeat( '<dl><dd>' , $indent_level ) . "<table{$attributes}>"\r
+                                IM ON UR array_push DOING $td_history , false\r
+                                IM ON UR array_push DOING $last_tag_history , ''\r
+                                IM ON UR array_push DOING $tr_history , false\r
+                                IM ON UR array_push DOING $tr_attributes , ''\r
+                                IM ON UR array_push DOING $has_opened_tr , false\r
+                        ORLY count( $td_history ) == 0\r
+                                BTW Don't do any of the following\r
+                                out HAS MOAR $outLine."\n";\r
+                               continue;\r
+                        ORLY substr( $line , 0 , 2 ) === '|}'\r
+                                BTW We are ending a table\r
+                                I HAS line IZ '</table>' . substr( $line , 2 )\r
+                                I HAS last_tag IZ array_pop( $last_tag_history )\r
+\r
+                                IZ !array_pop( $has_opened_tr )\r
+                                        I HAS line IZ "<tr><td></td></tr>{$line}"\r
+                                KTHX\r
+\r
+                                IZ array_pop( $tr_history )\r
+                                        I HAS line IZ "</tr>{$line}"\r
+                                KTHX\r
+\r
+                                IZ array_pop( $td_history )\r
+                                        I HAS line IZ "</{$last_tag}>{$line}"\r
+                                KTHX\r
+                                IM ON UR array_pop DOING $tr_attributes\r
+                                I HAS outLine IZ $line . str_repeat( '</dd></dl>' , $indent_level )\r
+                        ORLY substr( $line , 0 , 2 ) === '|-'\r
+                                BTW Now we have a table row\r
+                                I HAS line IZ preg_replace( '#^\|-+#', '', $line )\r
+\r
+                                BTW Whats after the tag is now only attributes\r
+                                I HAS attributes IZ $this->mStripState->unstripBoth( $line )\r
+                                I HAS attributes IZ Sanitizer::fixTagAttributes( $attributes, 'tr' )\r
+                                IM ON UR array_pop DOING $tr_attributes\r
+                                IM ON UR array_push DOING $tr_attributes, $attributes\r
+\r
+                                I HAS line IZ ''\r
+                                I HAS last_tag IZ array_pop( $last_tag_history )\r
+                                IM ON UR array_pop DOING $has_opened_tr\r
+                                IM ON UR array_push DOING $has_opened_tr , true\r
+\r
+                                IZ array_pop( $tr_history )\r
+                                        I HAS line IZ '</tr>'\r
+                                KTHX\r
+\r
+                                IZ array_pop( $td_history )\r
+                                        I HAS line IZ "</{$last_tag}>{$line}"\r
+                                KTHX\r
+\r
+                                I HAS outLine IZ $line\r
+                                IM ON UR array_push DOING $tr_history , false\r
+                                IM ON UR array_push DOING $td_history , false\r
+                                IM ON UR array_push DOING $last_tag_history , ''\r
+                        ORLY $first_character === '|' || $first_character === '!' || substr( $line , 0 , 2 )  === '|+'\r
+                                BTW This might be cell elements, td, th or captions\r
+                                IZ substr( $line , 0 , 2 ) === '|+'\r
+                                        I HAS first_character IZ '+'\r
+                                        I HAS line IZ substr( $line , 1 )\r
+                                KTHX\r
+\r
+                                I HAS line IZ substr( $line , 1 )\r
+\r
+                                IZ $first_character === '!'\r
+                                        I HAS line IZ str_replace( '!!' , '||' , $line )\r
+                                KTHX\r
+\r
+                                BTW Split up multiple cells on the same line.\r
+                                BTW FIXME : This can result in improper nesting of tags processed\r
+                                BTW by earlier parser steps, but should avoid splitting up eg\r
+                                BTW attribute values containing literal "||".\r
+                                I HAS cells IZ StringUtils::explodeMarkup( '||' , $line )\r
+\r
+                                I HAS outLine IZ ''\r
+\r
+                                BTW Loop through each table cell\r
+                                IM IN UR cells ITZA cell\r
+                                        I HAS previous IZ ''\r
+                                        IZ $first_character !== '+'\r
+                                                I HAS tr_after IZ array_pop( $tr_attributes )\r
+                                                IZ !array_pop( $tr_history )\r
+                                                        I HAS previous IZ "<tr{$tr_after}>\n"\r
+                                                KTHX\r
+                                                IM ON UR array_push DOING $tr_history , true\r
+                                                IM ON UR array_push DOING $tr_attributes , ''\r
+                                                IM ON UR array_pop DOING $has_opened_tr\r
+                                                IM ON UR array_push DOING $has_opened_tr , true\r
+                                        KTHX\r
+\r
+                                        I HAS last_tag IZ array_pop( $last_tag_history )\r
+\r
+                                        IZ array_pop( $td_history )\r
+                                                I HAS previous IZ "</{$last_tag}>{$previous}"\r
+                                        KTHX\r
+\r
+                                        IZ $first_character === '|'\r
+                                                I HAS last_tag IZ 'td'\r
+                                        ORLY $first_character === '!'\r
+                                                I HAS last_tag IZ 'th'\r
+                                        ORLY $first_character === '+'\r
+                                                I HAS last_tag IZ 'caption'\r
+                                        NOWAI\r
+                                                I HAS last_tag IZ ''\r
+                                        KTHX\r
+\r
+                                        IM ON UR array_push DOING $last_tag_history , $last_tag\r
+\r
+                                        BTW A cell could contain both parameters and data\r
+                                        I HAS cell_data IZ explode( '|' , $cell , 2 )\r
+\r
+                                        BTW Bug 553: Note that a '|' inside an invalid link should not\r
+                                        BTW be mistaken as delimiting cell parameters\r
+                                        IZ strpos( $cell_data[0], '[[' ) !== false\r
+                                                I HAS cell IZ "{$previous}<{$last_tag}>{$cell}"\r
+                                        ORLY count( $cell_data ) == 1\r
+                                                I HAS cell IZ "{$previous}<{$last_tag}>{$cell_data[0]}"\r
+                                        NOWAI\r
+                                                I HAS attributes IZ $this->mStripState->unstripBoth( $cell_data[0] )\r
+                                                I HAS attributes IZ Sanitizer::fixTagAttributes( $attributes , $last_tag )\r
+                                                I HAS cell IZ "{$previous}<{$last_tag}{$attributes}>{$cell_data[1]}"\r
+                                        KTHX\r
+\r
+                                        outLine HAS MOAR $cell;\r
+                                        IM ON UR array_push DOING $td_history , true\r
+                                KTHX\r
+                        KTHX\r
+                        out HAS MOAR $outLine . "\n";\r
+                KTHX\r
+\r
+                BTW Closing open td, tr && table\r
+                STEALIN UR count( $td_history ) > 0\r
+                        IZ array_pop( $td_history )\r
+                                out HAS MOAR "</td>\n";\r
+                        KTHX\r
+                        IZ array_pop( $tr_history )\r
+                                out HAS MOAR "</tr>\n";\r
+                        KTHX\r
+                        IZ !array_pop( $has_opened_tr )\r
+                                out HAS MOAR "<tr><td></td></tr>\n" ;\r
+                        KTHX\r
+\r
+                        out HAS MOAR "</table>\n";\r
+                KTHX\r
+\r
+                BTW Remove trailing line-ending (b/c)\r
+                IZ substr( $out, -1 ) === "\n"\r
+                        I HAS out IZ substr( $out, 0, -1 )\r
+                KTHX\r
+\r
+                BTW special case: don't return empty table\r
+                IZ $out === "<table>\n<tr><td></td></tr>\n</table>"\r
+                        I HAS out IZ ''\r
+                KTHX\r
+\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+\r
+                I FOUND MAH $out\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Helper function for parse() that transforms wiki markup into\r
+         NOT WANT HTML. Only called for $mOutputType == self::OT_HTML.\r
+         NOT WANT \r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE internalParse WITH UR $text, $isMain = true, $frame=false\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+\r
+                I HAS origText IZ $text\r
+\r
+                BTW Hook to suspend the parser in this state\r
+                IZ !wfRunHooks( 'ParserBeforeInternalParse', array( &$this, &$text, &$this->mStripState ) )\r
+                        IM ON UR wfProfileOut DOING __METHOD__\r
+                        I FOUND MAH $text \r
+                KTHX\r
+\r
+                BTW if $frame is provided, then use $frame for replacing any variables\r
+                IZ $frame\r
+                        BTW use frame depth to infer how include/noinclude tags should be handled\r
+                        BTW depth=0 means this is the top-level document; otherwise it's an included document\r
+                        IZ !$frame->depth\r
+                                I HAS flag IZ 0\r
+                        NOWAI\r
+                                I HAS flag IZ Parser::PTD_FOR_INCLUSION\r
+                        I HAS dom IZ $this->preprocessToDom( $text, $flag )\r
+                        I HAS text IZ $frame->expand( $dom )\r
+                        KTHX\r
+                NOWAI\r
+                        BTW if $frame is not provided, then use old-style replaceVariables\r
+                        I HAS text IZ $this->replaceVariables( $text )\r
+                KTHX\r
+\r
+                I HAS text IZ Sanitizer::removeHTMLtags( $text, array( &$this, 'attributeStripCallback' ), false, array_keys( $this->mTransparentTagHooks ) )\r
+                IM ON UR wfRunHooks DOING 'InternalParseBeforeLinks', array( &$this, &$text, &$this->mStripState )\r
+\r
+                BTW Tables need to come after variable replacement for things to work\r
+                BTW properly; putting them before other transformations should keep\r
+                BTW exciting things like link expansions from showing up in surprising\r
+                BTW places.\r
+                I HAS text IZ $this->doTableStuff( $text )\r
+\r
+                I HAS text IZ preg_replace( '/(^|\n)-----*/', '\\1<hr />', $text )\r
+\r
+                I HAS text IZ $this->doDoubleUnderscore( $text )\r
+\r
+                I HAS text IZ $this->doHeadings( $text )\r
+                IZ $this->mOptions->getUseDynamicDates()\r
+                        I HAS df IZ DateFormatter::getInstance()\r
+                        I HAS text IZ $df->reformat( $this->mOptions->getDateFormat(), $text )\r
+                KTHX\r
+                I HAS text IZ $this->doAllQuotes( $text )\r
+                I HAS text IZ $this->replaceInternalLinks( $text )\r
+                I HAS text IZ $this->replaceExternalLinks( $text )\r
+\r
+                BTW replaceInternalLinks may sometimes leave behind\r
+                BTW absolute URLs, which have to be masked to hide them from replaceExternalLinks\r
+                I HAS text IZ str_replace( $this->mUniqPrefix.'NOPARSE', '', $text )\r
+\r
+                I HAS text IZ $this->doMagicLinks( $text )\r
+                I HAS text IZ $this->formatHeadings( $text, $origText, $isMain )\r
+\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Replace special strings like "ISBN xxx" and "RFC xxx" with\r
+         NOT WANT magic external links.\r
+         NOT WANT \r
+         NOT WANT DML\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE doMagicLinks WITH UR $text\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+                I HAS prots IZ $this->mUrlProtocols\r
+                I HAS urlChar IZ self::EXT_LINK_URL_CLASS\r
+                text IZ preg_replace_callback(\r
+                       '!(?:                           # Start cases\r
+                               (<a[ \t\r\n>].*?</a>) |     # m[1]: Skip link text\r
+                               (<.*?>) |                   # m[2]: Skip stuff inside HTML elements' . "\r
+                               (\\b(?:$prots)$urlChar+) |  # m[3]: Free external links" . '\r
+                               (?:RFC|PMID)\s+([0-9]+) |   # m[4]: RFC or PMID, capture number\r
+                               ISBN\s+(\b                  # m[5]: ISBN, capture number\r
+                                   (?: 97[89] [\ \-]? )?   # optional 13-digit ISBN prefix\r
+                                   (?: [0-9]  [\ \-]? ){9} # 9 digits with opt. delimiters\r
+                                   [0-9Xx]                 # check digit\r
+                                   \b)\r
+                       )!x', array( &$this, 'magicLinkCallback' ), $text );\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        SO IM LIKE magicLinkCallback WITH UR $m\r
+                IZ isset( $m[1] ) && $m[1] !== ''\r
+                        BTW Skip anchor\r
+                        I FOUND MAH $m[0]\r
+                ORLY isset( $m[2] ) && $m[2] !== ''\r
+                        BTW Skip HTML element\r
+                        I FOUND MAH $m[0]\r
+                ORLY isset( $m[3] ) && $m[3] !== ''\r
+                        BTW Free external link\r
+                        I FOUND MAH $this->makeFreeExternalLink( $m[0] )\r
+                ORLY isset( $m[4] ) && $m[4] !== ''\r
+                        BTW RFC or PMID\r
+                        I HAS CssClass IZ ''\r
+                        IZ substr( $m[0], 0, 3 ) === 'RFC'\r
+                                I HAS keyword IZ 'RFC'\r
+                                I HAS urlmsg IZ 'rfcurl'\r
+                                I HAS CssClass IZ 'mw-magiclink-rfc'\r
+                                I HAS id IZ $m[4]\r
+                        ORLY substr( $m[0], 0, 4 ) === 'PMID'\r
+                                I HAS keyword IZ 'PMID'\r
+                                I HAS urlmsg IZ 'pubmedurl'\r
+                                I HAS CssClass IZ 'mw-magiclink-pmid'\r
+                                I HAS id IZ $m[4]\r
+                        NOWAI\r
+                               throw new MWException( __METHOD__.': unrecognised match type "' .\r
+                                        IM ON UR substr DOING $m[0], 0, 20 ) . '"'\r
+                        KTHX\r
+                        I HAS url IZ wfMsg( $urlmsg, $id)\r
+                        I HAS sk IZ $this->mOptions->getSkin()\r
+                        I HAS la IZ $sk->getExternalLinkAttributes( "external $CssClass" )\r
+                        I FOUND MAH "<a href=\"{$url}\"{$la}>{$keyword} {$id}</a>"\r
+                ORLY isset( $m[5] ) && $m[5] !== ''\r
+                        BTW ISBN\r
+                        I HAS isbn IZ $m[5]\r
+                        num IZ strtr( $isbn, array(\r
+                               '-' => '',\r
+                               ' ' => '',\r
+                               'x' => 'X',\r
+                       ));\r
+                        I HAS titleObj IZ SpecialPage::getTitleFor( 'Booksources', $num )\r
+                       return'<a href="' .\r
+                               $titleObj->escapeLocalUrl() .\r
+                               "\" class=\"internal mw-magiclink-isbn\">ISBN $isbn</a>";\r
+                NOWAI\r
+                        I FOUND MAH $m[0]\r
+                KTHX\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Make a free external link, given a user-supplied URL\r
+         NOT WANT @return HTML\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE makeFreeExternalLink WITH UR $url\r
+                I HAS UR $wgContLang ON UR INTERNETS\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+\r
+                I HAS sk IZ $this->mOptions->getSkin()\r
+                I HAS trail IZ ''\r
+\r
+                BTW The characters '<' and '>' (which were escaped by\r
+                BTW removeHTMLtags()) should not be included in\r
+                BTW URLs, per RFC 2396.\r
+                I HAS m2 IZ EMPTY\r
+                IZ preg_match( '/&(lt|gt);/', $url, $m2, PREG_OFFSET_CAPTURE )\r
+                        I HAS trail IZ substr( $url, $m2[0][1] ) . $trail\r
+                        I HAS url IZ substr( $url, 0, $m2[0][1] )\r
+                KTHX\r
+\r
+                BTW Move trailing punctuation to $trail\r
+                I HAS sep IZ ',;\.:!?'\r
+                BTW If there is no left bracket, then consider right brackets fair game too\r
+                IZ strpos( $url, '(' ) === false\r
+                        sep HAS MOAR ')';\r
+                KTHX\r
+\r
+                I HAS numSepChars IZ strspn( strrev( $url ), $sep )\r
+                IZ $numSepChars\r
+                        I HAS trail IZ substr( $url, -$numSepChars ) . $trail\r
+                        I HAS url IZ substr( $url, 0, -$numSepChars )\r
+                KTHX\r
+\r
+                I HAS url IZ Sanitizer::cleanUrl( $url )\r
+\r
+                BTW Is this an external image?\r
+                I HAS text IZ $this->maybeMakeExternalImage( $url )\r
+                IZ $text === false\r
+                        BTW Not an image, make a link\r
+                        text IZ $sk->makeExternalLink( $url, $wgContLang->markNoConversion($url), true, 'free',\r
+                                IM ON UR SPECIAL getExternalLinkAttribs DOING $url )\r
+                        BTW Register it in the output object...\r
+                        BTW Replace unnecessary URL escape codes with their equivalent characters\r
+                        I HAS pasteurized IZ self::replaceUnusualEscapes( $url )\r
+                        IM ON UR SPECIAL mOutput->addExternalLink DOING $pasteurized\r
+                KTHX\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $text . $trail\r
+        KTHX\r
+\r
+\r
+        DO NOT WANT\r
+         NOT WANT Parse headers and return html\r
+         NOT WANT \r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE doHeadings WITH UR $text\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+               for ( $i = 6; $i >= 1; --$i ) {\r
+                        I HAS h IZ str_repeat( '=', $i )\r
+                        text IZ preg_replace( "/^$h(.+)$h\\s*$/m",\r
+                         "<h$i>\\1</h$i>", $text );\r
+                KTHX\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Replace single quotes with HTML markup\r
+         NOT WANT @private\r
+         NOT WANT @return string the altered text\r
+         WANT\r
+        SO IM LIKE doAllQuotes WITH UR $text\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+                I HAS outtext IZ ''\r
+                I HAS lines IZ StringUtils::explode( "\n", $text )\r
+                IM IN UR lines ITZA line\r
+                        outtext HAS MOAR $this->doQuotes( $line ) . "\n";\r
+                KTHX\r
+                I HAS outtext IZ substr( $outtext, 0,-1 )\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $outtext\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Helper function for doAllQuotes()\r
+         WANT\r
+        SO IM LIKE doQuotes WITH UR $text\r
+                I HAS arr IZ preg_split( "/(''+)/", $text, -1, PREG_SPLIT_DELIM_CAPTURE )\r
+                IZ count( $arr ) == 1\r
+                        I FOUND MAH $text\r
+                NOWAI\r
+                        BTW First, do some preliminary work. This may shift some apostrophes from\r
+                        BTW being mark-up to being text. It also counts the number of occurrences\r
+                        BTW of bold and italics mark-ups.\r
+                        I HAS i IZ 0\r
+                        I HAS numbold IZ 0\r
+                        I HAS numitalics IZ 0\r
+                        IM IN UR arr ITZA r\r
+                                IZ ( $i % 2 ) == 1\r
+                                        BTW If there are ever four apostrophes, assume the first is supposed to\r
+                                        BTW be text, and the remaining three constitute mark-up for bold text.\r
+                                        IZ strlen( $arr[$i] ) == 4\r
+                                               $arr[$i-1] .= "'";\r
+                                               $arr[$i] = "'''";\r
+                                        ORLY strlen( $arr[$i] ) > 5\r
+                                                BTW If there are more than 5 apostrophes in a row, assume they're all\r
+                                                BTW text except for the last 5.\r
+                                               $arr[$i-1] .= str_repeat( "'", strlen( $arr[$i] ) - 5 );\r
+                                               $arr[$i] = "'''''";\r
+                                        KTHX\r
+                                        BTW Count the number of occurrences of bold and italics mark-ups.\r
+                                        BTW We are not counting sequences of five apostrophes.\r
+                                        IZ strlen( $arr[$i] ) == 2 \r
+                                               $numitalics++;\r
+                                        ORLY strlen( $arr[$i] ) == 3 \r
+                                               $numbold++;\r
+                                        ORLY strlen( $arr[$i] ) == 5 \r
+                                               $numitalics++; \r
+                                               $numbold++;\r
+                                        KTHX\r
+                                KTHX\r
+                               $i++;\r
+                        KTHX\r
+\r
+                        BTW If there is an odd number of both bold and italics, it is likely\r
+                        BTW that one of the bold ones was meant to be an apostrophe followed\r
+                        BTW by italics. Which one we cannot know for certain, but it is more\r
+                        BTW likely to be one that has a single-letter word before it.\r
+                        IZ ( $numbold % 2 == 1 ) && ( $numitalics % 2 == 1 )\r
+                                I HAS i IZ 0\r
+                                I HAS firstsingleletterword IZ -1\r
+                                I HAS firstmultiletterword IZ -1\r
+                                I HAS firstspace IZ -1\r
+                                IM IN UR arr ITZA r\r
+                                        IZ ( $i % 2 == 1 ) and ( strlen( $r ) == 3 )\r
+                                                I HAS x1 IZ substr( $arr[$i-1], -1 )\r
+                                                I HAS x2 IZ substr( $arr[$i-1], -2, 1 )\r
+                                                IZ $x1 === ' '\r
+                                                        IZ $firstspace == -1\r
+                                                                I HAS firstspace IZ $i\r
+                                                        KTHX\r
+                                                KTHX elseif ( $x2 === ' ') {\r
+                                                        IZ $firstsingleletterword == -1 \r
+                                                                I HAS firstsingleletterword IZ $i\r
+                                                        KTHX\r
+                                                NOWAI\r
+                                                        IZ $firstmultiletterword == -1\r
+                                                                I HAS firstmultiletterword IZ $i\r
+                                                        KTHX\r
+                                                KTHX\r
+                                        KTHX\r
+                                       $i++;\r
+                                KTHX\r
+\r
+                                BTW If there is a single-letter word, use it!\r
+                                IZ $firstsingleletterword > -1\r
+                                       $arr[$firstsingleletterword] = "''";\r
+                                       $arr[$firstsingleletterword-1] .= "'";\r
+                                ORLY $firstmultiletterword > -1\r
+                                        BTW If not, but there's a multi-letter word, use that one.\r
+                                       $arr[$firstmultiletterword] = "''";\r
+                                       $arr[$firstmultiletterword-1] .= "'";\r
+                                ORLY $firstspace > -1\r
+                                        BTW ... otherwise use the first one that has neither.\r
+                                        BTW (notice that it is possible for all three to be -1 if, for example,\r
+                                        BTW there is only one pentuple-apostrophe in the line)\r
+                                       $arr[$firstspace] = "''";\r
+                                       $arr[$firstspace-1] .= "'";\r
+                                KTHX\r
+                        KTHX\r
+\r
+                        BTW Now let's actually convert our apostrophic mush to HTML!\r
+                        I HAS output IZ ''\r
+                        I HAS buffer IZ ''\r
+                        I HAS state IZ ''\r
+                        I HAS i IZ 0\r
+                        IM IN UR arr ITZA r\r
+                                IZ ( $i % 2 ) == 0\r
+                                        IZ $state === 'both'\r
+                                                buffer HAS MOAR $r;\r
+                                        NOWAI\r
+                                                output HAS MOAR $r;\r
+                                        KTHX\r
+                                NOWAI\r
+                                        IZ strlen( $r ) == 2\r
+                                                IZ $state === 'i'\r
+                                                        output HAS MOAR '</i>'; $state = '';\r
+                                                ORLY $state === 'bi'\r
+                                                        output HAS MOAR '</i>'; $state = 'b';\r
+                                                ORLY $state === 'ib'\r
+                                                        output HAS MOAR '</b></i><b>'; $state = 'b';\r
+                                                ORLY $state === 'both'\r
+                                                        output HAS MOAR '<b><i>'.$buffer.'</i>'; $state = 'b';\r
+                                                NOWAI # $state can be 'b' or ''\r
+                                                        output HAS MOAR '<i>'; $state .= 'i';\r
+                                                KTHX\r
+                                        ORLY strlen( $r ) == 3\r
+                                                IZ $state === 'b'\r
+                                                        output HAS MOAR '</b>'; $state = '';\r
+                                                ORLY $state === 'bi'\r
+                                                        output HAS MOAR '</i></b><i>'; $state = 'i';\r
+                                                ORLY $state === 'ib'\r
+                                                        output HAS MOAR '</b>'; $state = 'i';\r
+                                                ORLY $state === 'both'\r
+                                                        output HAS MOAR '<i><b>'.$buffer.'</b>'; $state = 'i';\r
+                                                NOWAI # $state can be 'i' or ''\r
+                                                        output HAS MOAR '<b>'; $state .= 'b';\r
+                                                KTHX\r
+                                        ORLY strlen( $r ) == 5\r
+                                                IZ $state === 'b'\r
+                                                        output HAS MOAR '</b><i>'; $state = 'i';\r
+                                                ORLY $state === 'i'\r
+                                                        output HAS MOAR '</i><b>'; $state = 'b';\r
+                                                ORLY $state === 'bi'\r
+                                                        output HAS MOAR '</i></b>'; $state = '';\r
+                                                ORLY $state === 'ib'\r
+                                                        output HAS MOAR '</b></i>'; $state = '';\r
+                                                ORLY $state === 'both'\r
+                                                        output HAS MOAR '<i><b>'.$buffer.'</b></i>'; $state = '';\r
+                                                NOWAI # ($state == '')\r
+                                                        I HAS buffer IZ ''; $state = 'both'\r
+                                                KTHX\r
+                                        KTHX\r
+                                KTHX\r
+                               $i++;\r
+                        KTHX\r
+                        BTW Now close all remaining tags.  Notice that the order is important.\r
+                        IZ $state === 'b' || $state === 'ib'\r
+                                output HAS MOAR '</b>';\r
+                        KTHX\r
+                        IZ $state === 'i' || $state === 'bi' || $state === 'ib'\r
+                                output HAS MOAR '</i>';\r
+                        KTHX\r
+                        IZ $state === 'bi'\r
+                                output HAS MOAR '</b>';\r
+                        KTHX\r
+                        BTW There might be lonely ''''', so make sure we have a buffer\r
+                        IZ $state === 'both' && $buffer\r
+                                output HAS MOAR '<b><i>'.$buffer.'</i></b>';\r
+                        KTHX\r
+                        I FOUND MAH $output\r
+                KTHX\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Replace external links (REL)\r
+         NOT WANT \r
+         NOT WANT Note: this is all very hackish and the order of execution matters a lot.\r
+         NOT WANT Make sure to run maintenance/parserTests.php if you change this code.\r
+         NOT WANT \r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE replaceExternalLinks WITH UR $text\r
+                I HAS UR $wgContLang ON UR INTERNETS\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+\r
+                I HAS sk IZ $this->mOptions->getSkin()\r
+\r
+                I HAS bits IZ preg_split( $this->mExtLinkBracketedRegex, $text, -1, PREG_SPLIT_DELIM_CAPTURE )\r
+                I HAS s IZ array_shift( $bits )\r
+\r
+                I HAS i IZ 0\r
+                STEALIN UR $i<count( $bits )\r
+                        I HAS url IZ $bits[$i++]\r
+                        I HAS protocol IZ $bits[$i++]\r
+                        I HAS text IZ $bits[$i++]\r
+                        I HAS trail IZ $bits[$i++]\r
+\r
+                        BTW The characters '<' and '>' (which were escaped by\r
+                        BTW removeHTMLtags()) should not be included in\r
+                        BTW URLs, per RFC 2396.\r
+                        I HAS m2 IZ EMPTY\r
+                        IZ preg_match( '/&(lt|gt);/', $url, $m2, PREG_OFFSET_CAPTURE )\r
+                                I HAS text IZ substr( $url, $m2[0][1] ) . ' ' . $text\r
+                                I HAS url IZ substr( $url, 0, $m2[0][1] )\r
+                        KTHX\r
+\r
+                        BTW If the link text is an image URL, replace it with an <img> tag\r
+                        BTW This happened by accident in the original parser, but some people used it extensively\r
+                        I HAS img IZ $this->maybeMakeExternalImage( $text )\r
+                        IZ $img !== false\r
+                                I HAS text IZ $img\r
+                        KTHX\r
+\r
+                        I HAS dtrail IZ ''\r
+\r
+                        BTW Set linktype for CSS - if URL==text, link is essentially free\r
+                        I HAS linktype IZ ( $text === $url ) ? 'free' : 'text'\r
+\r
+                        BTW No link text, e.g. [http://domain.tld/some.link]\r
+                        IZ $text == ''\r
+                                BTW Autonumber if allowed. See bug #5918\r
+                                IZ strpos( wfUrlProtocols(), substr( $protocol, 0, strpos( $protocol, ':' ) ) ) !== false\r
+                                        I HAS langObj IZ $this->getFunctionLang()\r
+                                        I HAS text IZ '[' . $langObj->formatNum( ++$this->mAutonumber ) . ']'\r
+                                        I HAS linktype IZ 'autonumber'\r
+                                NOWAI\r
+                                        BTW Otherwise just use the URL\r
+                                        I HAS text IZ htmlspecialchars( $url )\r
+                                        I HAS linktype IZ 'free'\r
+                                KTHX\r
+                        NOWAI\r
+                                BTW Have link text, e.g. [http://domain.tld/some.link text]s\r
+                                BTW Check for trail\r
+                                IM ON UR list DOING $dtrail, $trail ) = Linker::splitTrail( $trail\r
+                        KTHX\r
+\r
+                        I HAS text IZ $wgContLang->markNoConversion( $text )\r
+\r
+                        I HAS url IZ Sanitizer::cleanUrl( $url )\r
+\r
+                        BTW Use the encoded URL\r
+                        BTW This means that users can paste URLs directly into the text\r
+                        BTW Funny characters like &ouml; aren't valid in URLs anyway\r
+                        BTW This was changed in August 2004\r
+                        s HAS MOAR $sk->makeExternalLink( $url, $text, false, $linktype,\r
+                               $this->getExternalLinkAttribs( $url ) ) . $dtrail . $trail;\r
+\r
+                        BTW Register link in the output object.\r
+                        BTW Replace unnecessary URL escape codes with the referenced character\r
+                        BTW This prevents spammers from hiding links from the filters\r
+                        I HAS pasteurized IZ self::replaceUnusualEscapes( $url )\r
+                        IM ON UR SPECIAL mOutput->addExternalLink DOING $pasteurized\r
+                KTHX\r
+\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $s\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Get an associative array of additional HTML attributes appropriate for a\r
+         NOT WANT particular external link.  This currently may include rel => nofollow\r
+         NOT WANT (depending on configuration, namespace, and the URL's domain) and/or a\r
+         NOT WANT target attribute (depending on configuration).\r
+         NOT WANT \r
+         NOT WANT @param string $url Optional URL, to extract the domain from for rel =>\r
+         NOT WANT   nofollow if appropriate\r
+         NOT WANT @return array Associative array of HTML attributes\r
+         WANT\r
+        SO IM LIKE getExternalLinkAttribs WITH UR $url = false\r
+                I HAS attribs IZ EMPTY\r
+                I HAS UR $wgNoFollowLinks, $wgNoFollowNsExceptions ON UR INTERNETS\r
+                I HAS ns IZ $this->mTitle->getNamespace()\r
+                IZ $wgNoFollowLinks && !in_array( $ns, $wgNoFollowNsExceptions )\r
+                       $attribs['rel'] = 'nofollow';\r
+\r
+                        I HAS UR $wgNoFollowDomainExceptions ON UR INTERNETS\r
+                        IZ $wgNoFollowDomainExceptions\r
+                                I HAS bits IZ wfParseUrl( $url )\r
+                                IZ is_array( $bits ) && isset( $bits['host'] )\r
+                                        IM IN UR wgNoFollowDomainExceptions ITZA domain\r
+                                                IZ substr( $bits['host'], -strlen( $domain ) ) == $domain\r
+                                                        IM ON UR unset DOING $attribs['rel']\r
+                                                       break;\r
+                                                KTHX\r
+                                        KTHX\r
+                                KTHX\r
+                        KTHX\r
+                KTHX\r
+                IZ $this->mOptions->getExternalLinkTarget()\r
+                       $attribs['target'] = $this->mOptions->getExternalLinkTarget();\r
+                KTHX\r
+                I FOUND MAH $attribs\r
+        KTHX\r
+\r
+\r
+        DO NOT WANT\r
+         NOT WANT Replace unusual URL escape codes with their equivalent characters\r
+         NOT WANT @param string\r
+         NOT WANT @return string\r
+         NOT WANT @static\r
+         NOT WANT @todo  This can merge genuinely required bits in the path or query string,\r
+         NOT WANT        breaking legit URLs. A proper fix would treat the various parts of\r
+         NOT WANT        the URL differently; as a workaround, just use the output for\r
+         NOT WANT        statistical records, not for actual linking/output.\r
+         WANT\r
+        SO IM ALWAYS LIKE replaceUnusualEscapes WITH UR $url\r
+               return preg_replace_callback( '/%[0-9A-Fa-f]{2}/',\r
+                        IM ON UR array DOING __CLASS__, 'replaceUnusualEscapesCallback' ), $url\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Callback function used in replaceUnusualEscapes().\r
+         NOT WANT Replaces unusual URL escape codes with their equivalent character\r
+         NOT WANT @static\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM ALWAYS LIKE replaceUnusualEscapesCallback WITH UR $matches\r
+                I HAS char IZ urldecode( $matches[0] )\r
+                I HAS ord IZ ord( $char )\r
+                BTW Is it an unsafe or HTTP reserved character according to RFC 1738?\r
+                IZ $ord > 32 && $ord < 127 && strpos( '<>"#{}|\^~[]`;/?', $char ) === false\r
+                        BTW No, shouldn't be escaped\r
+                        I FOUND MAH $char\r
+                NOWAI\r
+                        BTW Yes, leave it escaped\r
+                        I FOUND MAH $matches[0]\r
+                KTHX\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT make an image if it's allowed, either through the global\r
+         NOT WANT option, through the exception, or through the on-wiki whitelist\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE maybeMakeExternalImage WITH UR $url\r
+                I HAS sk IZ $this->mOptions->getSkin()\r
+                I HAS imagesfrom IZ $this->mOptions->getAllowExternalImagesFrom()\r
+                I HAS imagesexception IZ !empty( $imagesfrom )\r
+                I HAS text IZ false\r
+                BTW $imagesfrom could be either a single string or an array of strings, parse out the latter\r
+                IZ $imagesexception && is_array( $imagesfrom )\r
+                        I HAS imagematch IZ false\r
+                        IM IN UR imagesfrom ITZA match\r
+                                IZ strpos( $url, $match ) === 0\r
+                                        I HAS imagematch IZ true\r
+                                       break;\r
+                                KTHX\r
+                        KTHX\r
+                ORLY $imagesexception\r
+                        I HAS imagematch IZ ( strpos( $url, $imagesfrom ) === 0 )\r
+                NOWAI\r
+                        I HAS imagematch IZ false\r
+                KTHX\r
+               if ( $this->mOptions->getAllowExternalImages()\r
+                    || ( $imagesexception && $imagematch ) ) {\r
+                        IZ preg_match( self::EXT_IMAGE_REGEX, $url )\r
+                                BTW Image found\r
+                                I HAS text IZ $sk->makeExternalImage( $url )\r
+                        KTHX\r
+                KTHX\r
+               if ( !$text && $this->mOptions->getEnableImageWhitelist()\r
+                        && preg_match( self::EXT_IMAGE_REGEX, $url ) ) {\r
+                        I HAS whitelist IZ explode( "\n", wfMsgForContent( 'external_image_whitelist' ) )\r
+                        IM IN UR whitelist ITZA entry\r
+                                BTW Sanitize the regex fragment, make it case-insensitive, ignore blank entries/comments\r
+                                IZ strpos( $entry, '#' ) === 0 || $entry === ''\r
+                                       continue;\r
+                                KTHX\r
+                                IZ preg_match( '/' . str_replace( '/', '\\/', $entry ) . '/i', $url )\r
+                                        BTW Image matches a whitelist entry\r
+                                        I HAS text IZ $sk->makeExternalImage( $url )\r
+                                       break;\r
+                                KTHX\r
+                        KTHX\r
+                KTHX\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Process [[ ]] wikilinks\r
+         NOT WANT @return processed text\r
+         NOT WANT \r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE replaceInternalLinks WITH UR $s\r
+                IM ON UR SPECIAL mLinkHolders->merge DOING $this->replaceInternalLinks2( $s )\r
+                I FOUND MAH $s\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Process [[ ]] wikilinks (RIL)\r
+         NOT WANT @return LinkHolderArray\r
+         NOT WANT \r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE replaceInternalLinks2 WITH UR &$s\r
+                I HAS UR $wgContLang ON UR INTERNETS\r
+\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+\r
+                IM ON UR wfProfileIn DOING __METHOD__.'-setup'\r
+               static $tc = FALSE, $e1, $e1_img;\r
+                BTW the % is needed to support urlencoded titles as well\r
+                IZ !$tc\r
+                        I HAS tc IZ Title::legalChars() . '#%'\r
+                        BTW Match a link having the form [[namespace:link|alternate]]trail\r
+                        I HAS e1 IZ "/^([{$tc}]+)(?:\\|(.+?))?]](.*)\$/sD"\r
+                        BTW Match cases where there is no "]]", which might still be images\r
+                        I HAS e1_img IZ "/^([{$tc}]+)\\|(.*)\$/sD"\r
+                KTHX\r
+\r
+                I HAS sk IZ $this->mOptions->getSkin()\r
+                I HAS holders IZ new LinkHolderArray( $this )\r
+\r
+                BTW split the entire text string on occurences of [[\r
+                I HAS a IZ StringUtils::explode( '[[', ' ' . $s )\r
+                BTW get the first element (all text up to first [[), and remove the space we added\r
+                I HAS s IZ $a->current()\r
+               $a->next();\r
+                I HAS line IZ $a->current() # Workaround for broken ArrayIterator::next() that returns "void"\r
+                I HAS s IZ substr( $s, 1 )\r
+\r
+                I HAS useLinkPrefixExtension IZ $wgContLang->linkPrefixExtension()\r
+                I HAS e2\r
+                IZ $useLinkPrefixExtension\r
+                        BTW Match the end of a line for a word that's not followed by whitespace,\r
+                        BTW e.g. in the case of 'The Arab al[[Razi]]', 'al' will be matched\r
+                        I HAS e2 IZ wfMsgForContent( 'linkprefix' )\r
+                KTHX\r
+\r
+                IZ is_null( $this->mTitle )\r
+                        IM ON UR wfProfileOut DOING __METHOD__.'-setup'\r
+                        IM ON UR wfProfileOut DOING __METHOD__\r
+                       throw new MWException( __METHOD__.": \$this->mTitle is null\n" );\r
+                KTHX\r
+                I HAS nottalk IZ !$this->mTitle->isTalkPage()\r
+\r
+                IZ $useLinkPrefixExtension\r
+                        I HAS m IZ EMPTY\r
+                        IZ preg_match( $e2, $s, $m )\r
+                                I HAS first_prefix IZ $m[2]\r
+                        NOWAI\r
+                                I HAS first_prefix IZ false\r
+                        KTHX\r
+                NOWAI\r
+                        I HAS prefix IZ ''\r
+                KTHX\r
+\r
+                IZ $wgContLang->hasVariants()\r
+                        I HAS selflink IZ $wgContLang->convertLinkToAllVariants( $this->mTitle->getPrefixedText() )\r
+                NOWAI\r
+                        I HAS selflink IZ BUCKET $this->mTitle->getPrefixedText() );\r
+                KTHX\r
+                I HAS useSubpages IZ $this->areSubpagesAllowed()\r
+                IM ON UR wfProfileOut DOING __METHOD__.'-setup'\r
+\r
+                BTW Loop for each link\r
+               for ( ; $line !== false && $line !== null ; $a->next(), $line = $a->current() ) {\r
+                        BTW Check for excessive memory usage\r
+                        IZ $holders->isBig()\r
+                                BTW Too big\r
+                                BTW Do the existence check, replace the link holders and clear the array\r
+                               $holders->replace( $s );\r
+                               $holders->clear();\r
+                        KTHX\r
+\r
+                        IZ $useLinkPrefixExtension\r
+                                IM ON UR wfProfileIn DOING __METHOD__.'-prefixhandling'\r
+                                IZ preg_match( $e2, $s, $m )\r
+                                        I HAS prefix IZ $m[2]\r
+                                        I HAS s IZ $m[1]\r
+                                NOWAI\r
+                                       $prefix='';\r
+                                KTHX\r
+                                BTW first link\r
+                                IZ $first_prefix\r
+                                        I HAS prefix IZ $first_prefix\r
+                                        I HAS first_prefix IZ false\r
+                                KTHX\r
+                                IM ON UR wfProfileOut DOING __METHOD__.'-prefixhandling'\r
+                        KTHX\r
+\r
+                        I HAS might_be_img IZ false\r
+\r
+                        IM ON UR wfProfileIn DOING __METHOD__."-e1"\r
+                        IZ preg_match( $e1, $line, $m ) # page with normal text or alt\r
+                                I HAS text IZ $m[2]\r
+                                BTW If we get a ] at the beginning of $m[3] that means we have a link that's something like:\r
+                                BTW [[Image:Foo.jpg|[http://example.com desc]]] <- having three ] in a row fucks up,\r
+                                BTW the real problem is with the $e1 regex\r
+                                BTW See bug 1300.\r
+                                BTW \r
+                                BTW Still some problems for cases where the ] is meant to be outside punctuation,\r
+                                BTW and no image is in sight. See bug 2095.\r
+                                BTW \r
+                               if ( $text !== '' &&\r
+                                       substr( $m[3], 0, 1 ) === ']' &&\r
+                                       strpos( $text, '[' ) !== false\r
+                               )\r
+                               {\r
+                                        text HAS MOAR ']'; # so that replaceExternalLinks($text) works later\r
+                                       $m[3] = substr( $m[3], 1 );\r
+                                KTHX\r
+                                BTW fix up urlencoded title texts\r
+                                IZ strpos( $m[1], '%' ) !== false\r
+                                        BTW Should anchors '#' also be rejected?\r
+                                       $m[1] = str_replace( array('<', '>'), array('&lt;', '&gt;'), urldecode( $m[1] ) );\r
+                                KTHX\r
+                                I HAS trail IZ $m[3]\r
+                        ORLY preg_match( $e1_img, $line, $m ) # Invalid, but might be an image with a link in its caption\r
+                                I HAS might_be_img IZ true\r
+                                I HAS text IZ $m[2]\r
+                                IZ strpos( $m[1], '%' ) !== false\r
+                                       $m[1] = urldecode( $m[1] );\r
+                                KTHX\r
+                                I HAS trail IZ ""\r
+                        NOWAI # Invalid form; output directly\r
+                                s HAS MOAR $prefix . '[[' . $line ;\r
+                                IM ON UR wfProfileOut DOING __METHOD__."-e1"\r
+                               continue;\r
+                        KTHX\r
+                        IM ON UR wfProfileOut DOING __METHOD__."-e1"\r
+                        IM ON UR wfProfileIn DOING __METHOD__."-misc"\r
+\r
+                        BTW Don't allow internal links to pages containing\r
+                        BTW PROTO: where PROTO is a valid URL protocol; these\r
+                        BTW should be external links.\r
+                        IZ preg_match( '/^\b(?:' . wfUrlProtocols() . ')/', $m[1] )\r
+                                s HAS MOAR $prefix . '[[' . $line ;\r
+                                IM ON UR wfProfileOut DOING __METHOD__."-misc"\r
+                               continue;\r
+                        KTHX\r
+\r
+                        BTW Make subpage if necessary\r
+                        IZ $useSubpages\r
+                                I HAS link IZ $this->maybeDoSubpageLink( $m[1], $text )\r
+                        NOWAI\r
+                                I HAS link IZ $m[1]\r
+                        KTHX\r
+\r
+                        I HAS noforce IZ ( substr( $m[1], 0, 1 ) !== ':' )\r
+                        IZ !$noforce\r
+                                BTW Strip off leading ':'\r
+                                I HAS link IZ substr( $link, 1 )\r
+                        KTHX\r
+\r
+                        IM ON UR wfProfileOut DOING __METHOD__."-misc"\r
+                        IM ON UR wfProfileIn DOING __METHOD__."-title"\r
+                        I HAS nt IZ Title::newFromText( $this->mStripState->unstripNoWiki( $link ) )\r
+                        IZ $nt === null\r
+                                s HAS MOAR $prefix . '[[' . $line;\r
+                                IM ON UR wfProfileOut DOING __METHOD__."-title"\r
+                               continue;\r
+                        KTHX\r
+\r
+                        I HAS ns IZ $nt->getNamespace()\r
+                        I HAS iw IZ $nt->getInterWiki()\r
+                        IM ON UR wfProfileOut DOING __METHOD__."-title"\r
+\r
+                        IZ $might_be_img # if this is actually an invalid link\r
+                                IM ON UR wfProfileIn DOING __METHOD__."-might_be_img"\r
+                                IZ $ns == NS_FILE && $noforce # but might be an image\r
+                                        I HAS found IZ false\r
+                                        STEALIN UR true\r
+                                                BTW look at the next 'line' to see if we can close it there\r
+                                               $a->next();\r
+                                                I HAS next_line IZ $a->current()\r
+                                                IZ $next_line === false || $next_line === null\r
+                                                       break;\r
+                                                KTHX\r
+                                                I HAS m IZ explode( ']]', $next_line, 3 )\r
+                                                IZ count( $m ) == 3\r
+                                                        BTW the first ]] closes the inner link, the second the image\r
+                                                        I HAS found IZ true\r
+                                                        text HAS MOAR "[[{$m[0]}]]{$m[1]}";\r
+                                                        I HAS trail IZ $m[2]\r
+                                                       break;\r
+                                                ORLY count( $m ) == 2\r
+                                                        BTW if there's exactly one ]] that's fine, we'll keep looking\r
+                                                        text HAS MOAR "[[{$m[0]}]]{$m[1]}";\r
+                                                NOWAI\r
+                                                        BTW if $next_line is invalid too, we need look no further\r
+                                                        text HAS MOAR '[[' . $next_line;\r
+                                                       break;\r
+                                                KTHX\r
+                                        KTHX\r
+                                        IZ !$found\r
+                                                BTW we couldn't find the end of this imageLink, so output it raw\r
+                                                BTW but don't ignore what might be perfectly normal links in the text we've examined\r
+                                               $holders->merge( $this->replaceInternalLinks2( $text ) );\r
+                                                s HAS MOAR "{$prefix}[[$link|$text";\r
+                                                BTW note: no $trail, because without an end, there *is* no trail\r
+                                                IM ON UR wfProfileOut DOING __METHOD__."-might_be_img"\r
+                                               continue;\r
+                                        KTHX\r
+                                NOWAI # it's not an image, so output it raw\r
+                                        s HAS MOAR "{$prefix}[[$link|$text";\r
+                                        BTW note: no $trail, because without an end, there *is* no trail\r
+                                        IM ON UR wfProfileOut DOING __METHOD__."-might_be_img"\r
+                                       continue;\r
+                                KTHX\r
+                                IM ON UR wfProfileOut DOING __METHOD__."-might_be_img"\r
+                        KTHX\r
+\r
+                        I HAS wasblank IZ ( $text  == '' )\r
+                        IZ $wasblank\r
+                                I HAS text IZ $link\r
+                        KTHX\r
+\r
+                        BTW Link not escaped by : , create the various objects\r
+                        IZ $noforce\r
+\r
+                                BTW Interwikis\r
+                                IM ON UR wfProfileIn DOING __METHOD__."-interwiki"\r
+                                IZ $iw && $this->mOptions->getInterwikiMagic() && $nottalk && $wgContLang->getLanguageName( $iw )\r
+                                        IM ON UR SPECIAL mOutput->addLanguageLink DOING $nt->getFullText()\r
+                                        I HAS s IZ rtrim( $s . $prefix )\r
+                                        s HAS MOAR trim( $trail, "\n" ) == '' ? '': $prefix . $trail;\r
+                                        IM ON UR wfProfileOut DOING __METHOD__."-interwiki"\r
+                                       continue;\r
+                                KTHX\r
+                                IM ON UR wfProfileOut DOING __METHOD__."-interwiki"\r
+\r
+                                IZ $ns == NS_FILE\r
+                                        IM ON UR wfProfileIn DOING __METHOD__."-image"\r
+                                        IZ !wfIsBadImage( $nt->getDBkey(), $this->mTitle )\r
+                                                IZ $wasblank\r
+                                                        BTW if no parameters were passed, $text\r
+                                                        BTW becomes something like "File:Foo.png",\r
+                                                        BTW which we don't want to pass on to the\r
+                                                        BTW image generator\r
+                                                        I HAS text IZ ''\r
+                                                NOWAI\r
+                                                        BTW recursively parse links inside the image caption\r
+                                                        BTW actually, this will parse them in any other parameters, too,\r
+                                                        BTW but it might be hard to fix that, and it doesn't matter ATM\r
+                                                        I HAS text IZ $this->replaceExternalLinks( $text )\r
+                                                       $holders->merge( $this->replaceInternalLinks2( $text ) );\r
+                                                KTHX\r
+                                                BTW cloak any absolute URLs inside the image markup, so replaceExternalLinks() won't touch them\r
+                                                s HAS MOAR $prefix . $this->armorLinks( $this->makeImage( $nt, $text, $holders ) ) . $trail;\r
+                                        NOWAI\r
+                                                s HAS MOAR $prefix . $trail;\r
+                                        KTHX\r
+                                        IM ON UR SPECIAL mOutput->addImage DOING $nt->getDBkey()\r
+                                        IM ON UR wfProfileOut DOING __METHOD__."-image"\r
+                                       continue;\r
+\r
+                                KTHX\r
+\r
+                                IZ $ns == NS_CATEGORY\r
+                                        IM ON UR wfProfileIn DOING __METHOD__."-category"\r
+                                        I HAS s IZ rtrim( $s . "\n" ) # bug 87\r
+\r
+                                        IZ $wasblank\r
+                                                I HAS sortkey IZ $this->getDefaultSort()\r
+                                        NOWAI\r
+                                                I HAS sortkey IZ $text\r
+                                        KTHX\r
+                                        I HAS sortkey IZ Sanitizer::decodeCharReferences( $sortkey )\r
+                                        I HAS sortkey IZ str_replace( "\n", '', $sortkey )\r
+                                        I HAS sortkey IZ $wgContLang->convertCategoryKey( $sortkey )\r
+                                        IM ON UR SPECIAL mOutput->addCategory DOING $nt->getDBkey(), $sortkey\r
+\r
+                                        DO NOT WANT\r
+                                         NOT WANT Strip the whitespace Category links produce, see bug 87\r
+                                         NOT WANT @todo We might want to use trim($tmp, "\n") here.\r
+                                         WANT\r
+                                        s HAS MOAR trim( $prefix . $trail, "\n" ) == '' ? '': $prefix . $trail;\r
+\r
+                                        IM ON UR wfProfileOut DOING __METHOD__."-category"\r
+                                       continue;\r
+                                KTHX\r
+                        KTHX\r
+\r
+                        BTW Self-link checking\r
+                        IZ $nt->getFragment() === '' && $ns != NS_SPECIAL\r
+                                IZ in_array( $nt->getPrefixedText(), $selflink, true )\r
+                                        s HAS MOAR $prefix . $sk->makeSelfLinkObj( $nt, $text, '', $trail );\r
+                                       continue;\r
+                                KTHX\r
+                        KTHX\r
+\r
+                        BTW NS_MEDIA is a pseudo-namespace for linking directly to a file\r
+                        BTW FIXME: Should do batch file existence checks, see comment below\r
+                        IZ $ns == NS_MEDIA\r
+                                IM ON UR wfProfileIn DOING __METHOD__."-media"\r
+                                BTW Give extensions a chance to select the file revision for us\r
+                                I HAS skip IZ $time = false\r
+                                IM ON UR wfRunHooks DOING 'BeforeParserMakeImageLinkObj', array( &$this, &$nt, &$skip, &$time )\r
+                                IZ $skip\r
+                                        I HAS link IZ $sk->link( $nt )\r
+                                NOWAI\r
+                                        I HAS link IZ $sk->makeMediaLinkObj( $nt, $text, $time )\r
+                                KTHX\r
+                                BTW Cloak with NOPARSE to avoid replacement in replaceExternalLinks\r
+                                s HAS MOAR $prefix . $this->armorLinks( $link ) . $trail;\r
+                                IM ON UR SPECIAL mOutput->addImage DOING $nt->getDBkey()\r
+                                IM ON UR wfProfileOut DOING __METHOD__."-media"\r
+                               continue;\r
+                        KTHX\r
+\r
+                        IM ON UR wfProfileIn DOING __METHOD__."-always_known"\r
+                        BTW Some titles, such as valid special pages or files in foreign repos, should\r
+                        BTW be shown as bluelinks even though they're not included in the page table\r
+                        BTW \r
+                        BTW FIXME: isAlwaysKnown() can be expensive for file links; we should really do\r
+                        BTW batch file existence checks for NS_FILE and NS_MEDIA\r
+                        IZ $iw == '' && $nt->isAlwaysKnown()\r
+                                IM ON UR SPECIAL mOutput->addLink DOING $nt\r
+                                s HAS MOAR $this->makeKnownLinkHolder( $nt, $text, '', $trail, $prefix );\r
+                        NOWAI\r
+                                BTW Links will be added to the output link list after checking\r
+                                s HAS MOAR $holders->makeHolder( $nt, $text, '', $trail, $prefix );\r
+                        KTHX\r
+                        IM ON UR wfProfileOut DOING __METHOD__."-always_known"\r
+                KTHX\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $holders\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Make a link placeholder. The text returned can be later resolved to a real link with\r
+         NOT WANT replaceLinkHolders(). This is done for two reasons: firstly to avoid further\r
+         NOT WANT parsing of interwiki links, and secondly to allow all existence checks and\r
+         NOT WANT article length checks (for stub links) to be bundled into a single query.\r
+         NOT WANT \r
+         NOT WANT @deprecated\r
+         WANT\r
+        SO IM LIKE makeLinkHolder WITH UR &$nt, $text = '', $query = '', $trail = '', $prefix = ''\r
+                I FOUND MAH $this->mLinkHolders->makeHolder( $nt, $text, $query, $trail, $prefix )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Render a forced-blue link inline; protect against double expansion of\r
+         NOT WANT URLs if we're in a mode that prepends full URL prefixes to internal links.\r
+         NOT WANT Since this little disaster has to split off the trail text to avoid\r
+         NOT WANT breaking URLs in the following text without breaking trails on the\r
+         NOT WANT wiki links, it's been made into a horrible function.\r
+         NOT WANT \r
+         NOT WANT @param Title $nt\r
+         NOT WANT @param string $text\r
+         NOT WANT @param string $query\r
+         NOT WANT @param string $trail\r
+         NOT WANT @param string $prefix\r
+         NOT WANT @return string HTML-wikitext mix oh yuck\r
+         WANT\r
+        SO IM LIKE makeKnownLinkHolder WITH UR $nt, $text = '', $query = '', $trail = '', $prefix = ''\r
+                IM ON UR list DOING $inside, $trail ) = Linker::splitTrail( $trail\r
+                I HAS sk IZ $this->mOptions->getSkin()\r
+                BTW FIXME: use link() instead of deprecated makeKnownLinkObj()\r
+                I HAS link IZ $sk->makeKnownLinkObj( $nt, $text, $query, $inside, $prefix )\r
+                I FOUND MAH $this->armorLinks( $link ) . $trail\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Insert a NOPARSE hacky thing into any inline links in a chunk that's\r
+         NOT WANT going to go through further parsing steps before inline URL expansion.\r
+         NOT WANT \r
+         NOT WANT Not needed quite as much as it used to be since free links are a bit\r
+         NOT WANT more sensible these days. But bracketed links are still an issue.\r
+         NOT WANT \r
+         NOT WANT @param string more-or-less HTML\r
+         NOT WANT @return string less-or-more HTML with NOPARSE bits\r
+         WANT\r
+        SO IM LIKE armorLinks WITH UR $text\r
+               return preg_replace( '/\b(' . wfUrlProtocols() . ')/',\r
+                       "{$this->mUniqPrefix}NOPARSE$1", $text );\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Return true if subpage links should be expanded on this page.\r
+         NOT WANT @return bool\r
+         WANT\r
+        SO IM LIKE areSubpagesAllowed\r
+                BTW Some namespaces don't allow subpages\r
+                I FOUND MAH MWNamespace::hasSubpages( $this->mTitle->getNamespace() )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Handle link to subpage if necessary\r
+         NOT WANT @param string $target the source of the link\r
+         NOT WANT @param string &$text the link text, modified as necessary\r
+         NOT WANT @return string the full name of the link\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE maybeDoSubpageLink WITH UR $target, &$text\r
+                I FOUND MAH Linker::normalizeSubpageLink( $this->mTitle, $target, $text )\r
+        KTHX\r
+\r
+        DO NOT WANT#@+\r
+         NOT WANT Used by doBlockLevels()\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE closeParagraph\r
+                I HAS result IZ ''\r
+                IZ $this->mLastSection != ''\r
+                        I HAS result IZ '</' . $this->mLastSection  . ">\n"\r
+                KTHX\r
+                UR SPECIAL mInPre IZ false;\r
+                UR SPECIAL mLastSection IZ '';\r
+                I FOUND MAH $result\r
+        KTHX\r
+        DO NOT WANT\r
+         NOT WANT getCommon() returns the length of the longest common substring\r
+         NOT WANT of both arguments, starting at the beginning of both.\r
+         NOT WANT @private \r
+         WANT \r
+        SO IM LIKE getCommon WITH UR $st1, $st2\r
+                I HAS fl IZ strlen( $st1 )\r
+                I HAS shorter IZ strlen( $st2 )\r
+                IZ $fl < $shorter \r
+                        I HAS shorter IZ $fl \r
+                KTHX\r
+\r
+               for ( $i = 0; $i < $shorter; ++$i ) {\r
+                        IZ $st1{$i} != $st2{$i} \r
+                               break; \r
+                        KTHX\r
+                KTHX\r
+                I FOUND MAH $i\r
+        KTHX\r
+        DO NOT WANT\r
+         NOT WANT These next three functions open, continue, and close the list\r
+         NOT WANT element appropriate to the prefix character passed into them.\r
+         NOT WANT @private \r
+         WANT\r
+        SO IM LIKE openList WITH UR $char\r
+                I HAS result IZ $this->closeParagraph()\r
+\r
+                IZ '*' === $char \r
+                        result HAS MOAR '<ul><li>'; \r
+                ORLY '#' === $char \r
+                        result HAS MOAR '<ol><li>'; \r
+                ORLY ':' === $char \r
+                        result HAS MOAR '<dl><dd>'; \r
+                ORLY ';' === $char\r
+                        result HAS MOAR '<dl><dt>';\r
+                        UR SPECIAL mDTopen IZ true;\r
+                NOWAI \r
+                        I HAS result IZ '<!-- ERR 1 -->' \r
+                KTHX\r
+\r
+                I FOUND MAH $result\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT TODO: document\r
+         NOT WANT @param $char String\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE nextItem WITH UR $char\r
+                IZ '*' === $char || '#' === $char \r
+                        I FOUND MAH '</li><li>' \r
+                ORLY ':' === $char || ';' === $char\r
+                        I HAS close IZ '</dd>'\r
+                        IZ $this->mDTopen \r
+                                I HAS close IZ '</dt>' \r
+                        KTHX\r
+                        IZ ';' === $char\r
+                                UR SPECIAL mDTopen IZ true;\r
+                                I FOUND MAH $close . '<dt>'\r
+                        NOWAI\r
+                                UR SPECIAL mDTopen IZ false;\r
+                                I FOUND MAH $close . '<dd>'\r
+                        KTHX\r
+                KTHX\r
+                I FOUND MAH '<!-- ERR 2 -->'\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT TODO: document\r
+         NOT WANT @param $char String\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE closeList WITH UR $char\r
+                IZ '*' === $char \r
+                        I HAS text IZ '</li></ul>' \r
+                ORLY '#' === $char \r
+                        I HAS text IZ '</li></ol>' \r
+                ORLY ':' === $char\r
+                        IZ $this->mDTopen\r
+                                UR SPECIAL mDTopen IZ false;\r
+                                I HAS text IZ '</dt></dl>'\r
+                        NOWAI\r
+                                I HAS text IZ '</dd></dl>'\r
+                        KTHX\r
+                NOWAI  \r
+                        I FOUND MAH '<!-- ERR 3 -->' \r
+                KTHX\r
+                I FOUND MAH $text."\n"\r
+        KTHX\r
+        DO NOT WANT#@-*/\r
+\r
+        DO NOT WANT\r
+         NOT WANT Make lists from lines starting with ':', '*', '#', etc. (DBL)\r
+         NOT WANT \r
+         NOT WANT @param $linestart bool whether or not this is at the start of a line.\r
+         NOT WANT @private\r
+         NOT WANT @return string the lists rendered as HTML\r
+         WANT\r
+        SO IM LIKE doBlockLevels WITH UR $text, $linestart\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+\r
+                BTW Parsing through the text line by line.  The main thing\r
+                BTW happening here is handling of block-level elements p, pre,\r
+                BTW and making lists from lines starting with * # : etc.\r
+                BTW \r
+                I HAS textLines IZ StringUtils::explode( "\n", $text )\r
+\r
+                I HAS lastPrefix IZ $output = ''\r
+                UR SPECIAL mDTopen IZ $inBlockElem = false;\r
+                I HAS prefixLength IZ 0\r
+                I HAS paragraphStack IZ false\r
+\r
+                IM IN UR textLines ITZA oLine\r
+                        BTW Fix up $linestart\r
+                        IZ !$linestart\r
+                                output HAS MOAR $oLine;\r
+                                I HAS linestart IZ true\r
+                               continue;\r
+                        KTHX\r
+                        BTW * = ul\r
+                        BTW # = ol\r
+                        BTW ; = dt\r
+                        BTW : = dd\r
+\r
+                        I HAS lastPrefixLength IZ strlen( $lastPrefix )\r
+                        I HAS preCloseMatch IZ preg_match( '/<\\/pre/i', $oLine )\r
+                        I HAS preOpenMatch IZ preg_match( '/<pre/i', $oLine )\r
+                        BTW If not in a <pre> element, scan for and figure out what prefixes are there.\r
+                        IZ !$this->mInPre\r
+                                BTW Multiple prefixes may abut each other for nested lists.\r
+                                I HAS prefixLength IZ strspn( $oLine, '*#:;' )\r
+                                I HAS prefix IZ substr( $oLine, 0, $prefixLength )\r
+\r
+                                BTW eh?\r
+                                BTW ; and : are both from definition-lists, so they're equivalent\r
+                                BTW  for the purposes of determining whether or not we need to open/close\r
+                                BTW  elements.\r
+                                I HAS prefix2 IZ str_replace( ';', ':', $prefix )\r
+                                I HAS t IZ substr( $oLine, $prefixLength )\r
+                                UR SPECIAL mInPre IZ (bool)$preOpenMatch;\r
+                        NOWAI\r
+                                BTW Don't interpret any other prefixes in preformatted text\r
+                                I HAS prefixLength IZ 0\r
+                                I HAS prefix IZ $prefix2 = ''\r
+                                I HAS t IZ $oLine\r
+                        KTHX\r
+\r
+                        BTW List generation\r
+                        IZ $prefixLength && $lastPrefix === $prefix2\r
+                                BTW Same as the last item, so no need to deal with nesting or opening stuff\r
+                                output HAS MOAR $this->nextItem( substr( $prefix, -1 ) );\r
+                                I HAS paragraphStack IZ false\r
+\r
+                               if ( substr( $prefix, -1 ) === ';') {\r
+                                        BTW The one nasty exception: definition lists work like this:\r
+                                        BTW ; title : definition text\r
+                                        BTW So we check for : in the remainder text to split up the\r
+                                        BTW title and definition, without b0rking links.\r
+                                        I HAS term IZ $t2 = ''\r
+                                        IZ $this->findColonNoLinks( $t, $term, $t2 ) !== false\r
+                                                I HAS t IZ $t2\r
+                                                output HAS MOAR $term . $this->nextItem( ':' );\r
+                                        KTHX\r
+                                KTHX\r
+                        ORLY $prefixLength || $lastPrefixLength\r
+                                BTW We need to open or close prefixes, or both.\r
+\r
+                                BTW Either open or close a level...\r
+                                I HAS commonPrefixLength IZ $this->getCommon( $prefix, $lastPrefix )\r
+                                I HAS paragraphStack IZ false\r
+\r
+                                BTW Close all the prefixes which aren't shared.\r
+                                STEALIN UR $commonPrefixLength < $lastPrefixLength\r
+                                        output HAS MOAR $this->closeList( $lastPrefix[$lastPrefixLength-1] );\r
+                                       --$lastPrefixLength;\r
+                                KTHX\r
+\r
+                                BTW Continue the current prefix if appropriate.\r
+                                IZ $prefixLength <= $commonPrefixLength && $commonPrefixLength > 0\r
+                                        output HAS MOAR $this->nextItem( $prefix[$commonPrefixLength-1] );\r
+                                KTHX\r
+\r
+                                BTW Open prefixes where appropriate.\r
+                                STEALIN UR $prefixLength > $commonPrefixLength\r
+                                        I HAS char IZ substr( $prefix, $commonPrefixLength, 1 )\r
+                                        output HAS MOAR $this->openList( $char );\r
+\r
+                                        IZ ';' === $char\r
+                                                BTW FIXME: This is dupe of code above\r
+                                                IZ $this->findColonNoLinks( $t, $term, $t2 ) !== false\r
+                                                        I HAS t IZ $t2\r
+                                                        output HAS MOAR $term . $this->nextItem( ':' );\r
+                                                KTHX\r
+                                        KTHX\r
+                                       ++$commonPrefixLength;\r
+                                KTHX\r
+                                I HAS lastPrefix IZ $prefix2\r
+                        KTHX\r
+\r
+                        BTW If we have no prefixes, go to paragraph mode.\r
+                        IZ 0 == $prefixLength\r
+                                IM ON UR wfProfileIn DOING __METHOD__."-paragraph"\r
+                                BTW No prefix (not in list)--go to paragraph mode\r
+                                BTW XXX: use a stack for nestable elements like span, table and div\r
+                                I HAS openmatch IZ preg_match('/(?:<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<ol|<li|<\\/tr|<\\/td|<\\/th)/iS', $t )\r
+                                closematch IZ preg_match(\r
+                                       '/(?:<\\/table|<\\/blockquote|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|'.\r
+                                       '<td|<th|<\\/?div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<\\/?center)/iS', $t );\r
+                                IZ $openmatch or $closematch\r
+                                        I HAS paragraphStack IZ false\r
+                                       # TODO bug 5718: paragraph closed\r
+                                        output HAS MOAR $this->closeParagraph();\r
+                                        IZ $preOpenMatch and !$preCloseMatch\r
+                                                UR SPECIAL mInPre IZ true;\r
+                                        KTHX\r
+                                        IZ $closematch\r
+                                                I HAS inBlockElem IZ false\r
+                                        NOWAI\r
+                                                I HAS inBlockElem IZ true\r
+                                        KTHX\r
+                                ORLY !$inBlockElem && !$this->mInPre\r
+                                        IZ ' ' == substr( $t, 0, 1 ) and ( $this->mLastSection === 'pre' || trim( $t ) != '' )\r
+                                                BTW pre\r
+                                                IZ $this->mLastSection !== 'pre'\r
+                                                        I HAS paragraphStack IZ false\r
+                                                        output HAS MOAR $this->closeParagraph().'<pre>';\r
+                                                        UR SPECIAL mLastSection IZ 'pre';\r
+                                                KTHX\r
+                                                I HAS t IZ substr( $t, 1 )\r
+                                        NOWAI\r
+                                                BTW paragraph\r
+                                                IZ trim( $t ) == ''\r
+                                                        IZ $paragraphStack\r
+                                                                output HAS MOAR $paragraphStack.'<br />';\r
+                                                                I HAS paragraphStack IZ false\r
+                                                                UR SPECIAL mLastSection IZ 'p';\r
+                                                        NOWAI\r
+                                                                IZ $this->mLastSection !== 'p'\r
+                                                                        output HAS MOAR $this->closeParagraph();\r
+                                                                        UR SPECIAL mLastSection IZ '';\r
+                                                                        I HAS paragraphStack IZ '<p>'\r
+                                                                NOWAI\r
+                                                                        I HAS paragraphStack IZ '</p><p>'\r
+                                                                KTHX\r
+                                                        KTHX\r
+                                                NOWAI\r
+                                                        IZ $paragraphStack\r
+                                                                output HAS MOAR $paragraphStack;\r
+                                                                I HAS paragraphStack IZ false\r
+                                                                UR SPECIAL mLastSection IZ 'p';\r
+                                                        ORLY $this->mLastSection !== 'p'\r
+                                                                output HAS MOAR $this->closeParagraph().'<p>';\r
+                                                                UR SPECIAL mLastSection IZ 'p';\r
+                                                        KTHX\r
+                                                KTHX\r
+                                        KTHX\r
+                                KTHX\r
+                                IM ON UR wfProfileOut DOING __METHOD__."-paragraph"\r
+                        KTHX\r
+                        BTW somewhere above we forget to get out of pre block (bug 785)\r
+                        IZ $preCloseMatch && $this->mInPre\r
+                                UR SPECIAL mInPre IZ false;\r
+                        KTHX\r
+                        IZ $paragraphStack === false\r
+                                output HAS MOAR $t."\n";\r
+                        KTHX\r
+                KTHX\r
+                STEALIN UR $prefixLength\r
+                        output HAS MOAR $this->closeList( $prefix2[$prefixLength-1] );\r
+                       --$prefixLength;\r
+                KTHX\r
+                IZ $this->mLastSection != ''\r
+                        output HAS MOAR '</' . $this->mLastSection . '>';\r
+                        UR SPECIAL mLastSection IZ '';\r
+                KTHX\r
+\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $output\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Split up a string on ':', ignoring any occurences inside tags\r
+         NOT WANT to prevent illegal overlapping.\r
+         NOT WANT @param string $str the string to split\r
+         NOT WANT @param string &$before set to everything before the ':'\r
+         NOT WANT @param string &$after set to everything after the ':'\r
+         NOT WANT return string the position of the ':', or false if none found\r
+         WANT\r
+        SO IM LIKE findColonNoLinks WITH UR $str, &$before, &$after\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+\r
+                I HAS pos IZ strpos( $str, ':' )\r
+                IZ $pos === false\r
+                        BTW Nothing to find!\r
+                        IM ON UR wfProfileOut DOING __METHOD__\r
+                        I FOUND MAH false\r
+                KTHX\r
+\r
+                I HAS lt IZ strpos( $str, '<' )\r
+                IZ $lt === false || $lt > $pos\r
+                        BTW Easy; no tag nesting to worry about\r
+                        I HAS before IZ substr( $str, 0, $pos )\r
+                        I HAS after IZ substr( $str, $pos+1 )\r
+                        IM ON UR wfProfileOut DOING __METHOD__\r
+                        I FOUND MAH $pos\r
+                KTHX\r
+\r
+                BTW Ugly state machine to walk through avoiding tags.\r
+                I HAS state IZ self::COLON_STATE_TEXT\r
+                I HAS stack IZ 0\r
+                I HAS len IZ strlen( $str )\r
+               for( $i = 0; $i < $len; $i++ ) {\r
+                        I HAS c IZ $str{$i}\r
+\r
+                       switch( $state ) {\r
+                        BTW (Using the number is a performance hack for common cases)\r
+                       case 0: # self::COLON_STATE_TEXT:\r
+                               switch( $c ) {\r
+                               case "<":\r
+                                        BTW Could be either a <start> tag or an </end> tag\r
+                                        I HAS state IZ self::COLON_STATE_TAGSTART\r
+                                       break;\r
+                               case ":":\r
+                                        IZ $stack == 0\r
+                                                BTW We found it!\r
+                                                I HAS before IZ substr( $str, 0, $i )\r
+                                                I HAS after IZ substr( $str, $i + 1 )\r
+                                                IM ON UR wfProfileOut DOING __METHOD__\r
+                                                I FOUND MAH $i\r
+                                        KTHX\r
+                                        BTW Embedded in a tag; don't break it.\r
+                                       break;\r
+                               default:\r
+                                        BTW Skip ahead looking for something interesting\r
+                                        I HAS colon IZ strpos( $str, ':', $i )\r
+                                        IZ $colon === false\r
+                                                BTW Nothing else interesting\r
+                                                IM ON UR wfProfileOut DOING __METHOD__\r
+                                                I FOUND MAH false\r
+                                        KTHX\r
+                                        I HAS lt IZ strpos( $str, '<', $i )\r
+                                        IZ $stack === 0\r
+                                                IZ $lt === false || $colon < $lt\r
+                                                        BTW We found it!\r
+                                                        I HAS before IZ substr( $str, 0, $colon )\r
+                                                        I HAS after IZ substr( $str, $colon + 1 )\r
+                                                        IM ON UR wfProfileOut DOING __METHOD__\r
+                                                        I FOUND MAH $i\r
+                                                KTHX\r
+                                        KTHX\r
+                                        IZ $lt === false\r
+                                                BTW Nothing else interesting to find; abort!\r
+                                                BTW We're nested, but there's no close tags left. Abort!\r
+                                               break 2;\r
+                                        KTHX\r
+                                        BTW Skip ahead to next tag start\r
+                                        I HAS i IZ $lt\r
+                                        I HAS state IZ self::COLON_STATE_TAGSTART\r
+                                KTHX\r
+                               break;\r
+                       case 1: # self::COLON_STATE_TAG:\r
+                                BTW In a <tag>\r
+                               switch( $c ) {\r
+                               case ">":\r
+                                       $stack++;\r
+                                        I HAS state IZ self::COLON_STATE_TEXT\r
+                                       break;\r
+                               case "/":\r
+                                        BTW Slash may be followed by >?\r
+                                        I HAS state IZ self::COLON_STATE_TAGSLASH\r
+                                       break;\r
+                               default:\r
+                                        BTW ignore\r
+                                KTHX\r
+                               break;\r
+                       case 2: # self::COLON_STATE_TAGSTART:\r
+                               switch( $c ) {\r
+                               case "/":\r
+                                        I HAS state IZ self::COLON_STATE_CLOSETAG\r
+                                       break;\r
+                               case "!":\r
+                                        I HAS state IZ self::COLON_STATE_COMMENT\r
+                                       break;\r
+                               case ">":\r
+                                        BTW Illegal early close? This shouldn't happen D:\r
+                                        I HAS state IZ self::COLON_STATE_TEXT\r
+                                       break;\r
+                               default:\r
+                                        I HAS state IZ self::COLON_STATE_TAG\r
+                                KTHX\r
+                               break;\r
+                       case 3: # self::COLON_STATE_CLOSETAG:\r
+                                BTW In a </tag>\r
+                                IZ $c === ">"\r
+                                        I HAS stack--\r
+                                        IZ $stack < 0\r
+                                                IM ON UR wfDebug DOING __METHOD__.": Invalid input; too many close tags\n"\r
+                                                IM ON UR wfProfileOut DOING __METHOD__\r
+                                                I FOUND MAH false\r
+                                        KTHX\r
+                                        I HAS state IZ self::COLON_STATE_TEXT\r
+                                KTHX\r
+                               break;\r
+                       case self::COLON_STATE_TAGSLASH:\r
+                                IZ $c === ">"\r
+                                        BTW Yes, a self-closed tag <blah/>\r
+                                        I HAS state IZ self::COLON_STATE_TEXT\r
+                                NOWAI\r
+                                        BTW Probably we're jumping the gun, and this is an attribute\r
+                                        I HAS state IZ self::COLON_STATE_TAG\r
+                                KTHX\r
+                               break;\r
+                       case 5: # self::COLON_STATE_COMMENT:\r
+                                IZ $c === "-"\r
+                                        I HAS state IZ self::COLON_STATE_COMMENTDASH\r
+                                KTHX\r
+                               break;\r
+                       case self::COLON_STATE_COMMENTDASH:\r
+                                IZ $c === "-"\r
+                                        I HAS state IZ self::COLON_STATE_COMMENTDASHDASH\r
+                                NOWAI\r
+                                        I HAS state IZ self::COLON_STATE_COMMENT\r
+                                KTHX\r
+                               break;\r
+                       case self::COLON_STATE_COMMENTDASHDASH:\r
+                                IZ $c === ">"\r
+                                        I HAS state IZ self::COLON_STATE_TEXT\r
+                                NOWAI\r
+                                        I HAS state IZ self::COLON_STATE_COMMENT\r
+                                KTHX\r
+                               break;\r
+                       default:\r
+                               throw new MWException( "State machine error in " . __METHOD__ );\r
+                        KTHX\r
+                KTHX\r
+                IZ $stack > 0\r
+                        IM ON UR wfDebug DOING __METHOD__.": Invalid input; not enough close tags (stack $stack, state $state)\n"\r
+                        I FOUND MAH false\r
+                KTHX\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH false\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Return value of a magic variable (like PAGENAME)\r
+         NOT WANT \r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE getVariableValue WITH UR $index, $frame=false\r
+                I HAS UR $wgContLang, $wgSitename, $wgServer, $wgServerName ON UR INTERNETS\r
+                I HAS UR $wgScriptPath, $wgStylePath ON UR INTERNETS\r
+\r
+                DO NOT WANT\r
+                 NOT WANT Some of these require message or data lookups and can be\r
+                 NOT WANT expensive to check many times.\r
+                 WANT\r
+                IZ wfRunHooks( 'ParserGetVariableValueVarCache', array( &$this, &$this->mVarCache ) )\r
+                        IZ isset( $this->mVarCache[$index] )\r
+                                I FOUND MAH $this->mVarCache[$index]\r
+                        KTHX\r
+                KTHX\r
+\r
+                I HAS ts IZ wfTimestamp( TS_UNIX, $this->mOptions->getTimestamp() )\r
+                IM ON UR wfRunHooks DOING 'ParserGetVariableValueTs', array( &$this, &$ts )\r
+\r
+                BTW Use the time zone\r
+                I HAS UR $wgLocaltimezone ON UR INTERNETS\r
+                IZ isset( $wgLocaltimezone )\r
+                        I HAS oldtz IZ date_default_timezone_get()\r
+                        IM ON UR date_default_timezone_set DOING $wgLocaltimezone\r
+                KTHX\r
+\r
+                I HAS localTimestamp IZ date( 'YmdHis', $ts )\r
+                I HAS localMonth IZ date( 'm', $ts )\r
+                I HAS localMonth1 IZ date( 'n', $ts )\r
+                I HAS localMonthName IZ date( 'n', $ts )\r
+                I HAS localDay IZ date( 'j', $ts )\r
+                I HAS localDay2 IZ date( 'd', $ts )\r
+                I HAS localDayOfWeek IZ date( 'w', $ts )\r
+                I HAS localWeek IZ date( 'W', $ts )\r
+                I HAS localYear IZ date( 'Y', $ts )\r
+                I HAS localHour IZ date( 'H', $ts )\r
+                IZ isset( $wgLocaltimezone )\r
+                        IM ON UR date_default_timezone_set DOING $oldtz\r
+                KTHX\r
+\r
+               switch ( $index ) {\r
+                       case 'currentmonth':\r
+                                I HAS value IZ $wgContLang->formatNum( gmdate( 'm', $ts ) )\r
+                               break;\r
+                       case 'currentmonth1':\r
+                                I HAS value IZ $wgContLang->formatNum( gmdate( 'n', $ts ) )\r
+                               break;\r
+                       case 'currentmonthname':\r
+                                I HAS value IZ $wgContLang->getMonthName( gmdate( 'n', $ts ) )\r
+                               break;\r
+                       case 'currentmonthnamegen':\r
+                                I HAS value IZ $wgContLang->getMonthNameGen( gmdate( 'n', $ts ) )\r
+                               break;\r
+                       case 'currentmonthabbrev':\r
+                                I HAS value IZ $wgContLang->getMonthAbbreviation( gmdate( 'n', $ts ) )\r
+                               break;\r
+                       case 'currentday':\r
+                                I HAS value IZ $wgContLang->formatNum( gmdate( 'j', $ts ) )\r
+                               break;\r
+                       case 'currentday2':\r
+                                I HAS value IZ $wgContLang->formatNum( gmdate( 'd', $ts ) )\r
+                               break;\r
+                       case 'localmonth':\r
+                                I HAS value IZ $wgContLang->formatNum( $localMonth )\r
+                               break;\r
+                       case 'localmonth1':\r
+                                I HAS value IZ $wgContLang->formatNum( $localMonth1 )\r
+                               break;\r
+                       case 'localmonthname':\r
+                                I HAS value IZ $wgContLang->getMonthName( $localMonthName )\r
+                               break;\r
+                       case 'localmonthnamegen':\r
+                                I HAS value IZ $wgContLang->getMonthNameGen( $localMonthName )\r
+                               break;\r
+                       case 'localmonthabbrev':\r
+                                I HAS value IZ $wgContLang->getMonthAbbreviation( $localMonthName )\r
+                               break;\r
+                       case 'localday':\r
+                                I HAS value IZ $wgContLang->formatNum( $localDay )\r
+                               break;\r
+                       case 'localday2':\r
+                                I HAS value IZ $wgContLang->formatNum( $localDay2 )\r
+                               break;\r
+                       case 'pagename':\r
+                                I HAS value IZ wfEscapeWikiText( $this->mTitle->getText() )\r
+                               break;\r
+                       case 'pagenamee':\r
+                                I HAS value IZ $this->mTitle->getPartialURL()\r
+                               break;\r
+                       case 'fullpagename':\r
+                                I HAS value IZ wfEscapeWikiText( $this->mTitle->getPrefixedText() )\r
+                               break;\r
+                       case 'fullpagenamee':\r
+                                I HAS value IZ $this->mTitle->getPrefixedURL()\r
+                               break;\r
+                       case 'subpagename':\r
+                                I HAS value IZ wfEscapeWikiText( $this->mTitle->getSubpageText() )\r
+                               break;\r
+                       case 'subpagenamee':\r
+                                I HAS value IZ $this->mTitle->getSubpageUrlForm()\r
+                               break;\r
+                       case 'basepagename':\r
+                                I HAS value IZ wfEscapeWikiText( $this->mTitle->getBaseText() )\r
+                               break;\r
+                       case 'basepagenamee':\r
+                                I HAS value IZ wfUrlEncode( str_replace( ' ', '_', $this->mTitle->getBaseText() ) )\r
+                               break;\r
+                       case 'talkpagename':\r
+                                IZ $this->mTitle->canTalk()\r
+                                        I HAS talkPage IZ $this->mTitle->getTalkPage()\r
+                                        I HAS value IZ wfEscapeWikiText( $talkPage->getPrefixedText() )\r
+                                NOWAI\r
+                                        I HAS value IZ ''\r
+                                KTHX\r
+                               break;\r
+                       case 'talkpagenamee':\r
+                                IZ $this->mTitle->canTalk()\r
+                                        I HAS talkPage IZ $this->mTitle->getTalkPage()\r
+                                        I HAS value IZ $talkPage->getPrefixedUrl()\r
+                                NOWAI\r
+                                        I HAS value IZ ''\r
+                                KTHX\r
+                               break;\r
+                       case 'subjectpagename':\r
+                                I HAS subjPage IZ $this->mTitle->getSubjectPage()\r
+                                I HAS value IZ wfEscapeWikiText( $subjPage->getPrefixedText() )\r
+                               break;\r
+                       case 'subjectpagenamee':\r
+                                I HAS subjPage IZ $this->mTitle->getSubjectPage()\r
+                                I HAS value IZ $subjPage->getPrefixedUrl()\r
+                               break;\r
+                       case 'revisionid':\r
+                                BTW Let the edit saving system know we should parse the page\r
+                                BTW *after* a revision ID has been assigned.\r
+                                IM ON UR SPECIAL mOutput->setFlag DOING 'vary-revision'\r
+                                IM ON UR wfDebug DOING __METHOD__ . ": {{REVISIONID}} used, setting vary-revision...\n"\r
+                                I HAS value IZ $this->mRevisionId\r
+                               break;\r
+                       case 'revisionday':\r
+                                BTW Let the edit saving system know we should parse the page\r
+                                BTW *after* a revision ID has been assigned. This is for null edits.\r
+                                IM ON UR SPECIAL mOutput->setFlag DOING 'vary-revision'\r
+                                IM ON UR wfDebug DOING __METHOD__ . ": {{REVISIONDAY}} used, setting vary-revision...\n"\r
+                                I HAS value IZ intval( substr( $this->getRevisionTimestamp(), 6, 2 ) )\r
+                               break;\r
+                       case 'revisionday2':\r
+                                BTW Let the edit saving system know we should parse the page\r
+                                BTW *after* a revision ID has been assigned. This is for null edits.\r
+                                IM ON UR SPECIAL mOutput->setFlag DOING 'vary-revision'\r
+                                IM ON UR wfDebug DOING __METHOD__ . ": {{REVISIONDAY2}} used, setting vary-revision...\n"\r
+                                I HAS value IZ substr( $this->getRevisionTimestamp(), 6, 2 )\r
+                               break;\r
+                       case 'revisionmonth':\r
+                                BTW Let the edit saving system know we should parse the page\r
+                                BTW *after* a revision ID has been assigned. This is for null edits.\r
+                                IM ON UR SPECIAL mOutput->setFlag DOING 'vary-revision'\r
+                                IM ON UR wfDebug DOING __METHOD__ . ": {{REVISIONMONTH}} used, setting vary-revision...\n"\r
+                                I HAS value IZ intval( substr( $this->getRevisionTimestamp(), 4, 2 ) )\r
+                               break;\r
+                       case 'revisionyear':\r
+                                BTW Let the edit saving system know we should parse the page\r
+                                BTW *after* a revision ID has been assigned. This is for null edits.\r
+                                IM ON UR SPECIAL mOutput->setFlag DOING 'vary-revision'\r
+                                IM ON UR wfDebug DOING __METHOD__ . ": {{REVISIONYEAR}} used, setting vary-revision...\n"\r
+                                I HAS value IZ substr( $this->getRevisionTimestamp(), 0, 4 )\r
+                               break;\r
+                       case 'revisiontimestamp':\r
+                                BTW Let the edit saving system know we should parse the page\r
+                                BTW *after* a revision ID has been assigned. This is for null edits.\r
+                                IM ON UR SPECIAL mOutput->setFlag DOING 'vary-revision'\r
+                                IM ON UR wfDebug DOING __METHOD__ . ": {{REVISIONTIMESTAMP}} used, setting vary-revision...\n"\r
+                                I HAS value IZ $this->getRevisionTimestamp()\r
+                               break;\r
+                       case 'revisionuser':\r
+                                BTW Let the edit saving system know we should parse the page\r
+                                BTW *after* a revision ID has been assigned. This is for null edits.\r
+                                IM ON UR SPECIAL mOutput->setFlag DOING 'vary-revision'\r
+                                IM ON UR wfDebug DOING __METHOD__ . ": {{REVISIONUSER}} used, setting vary-revision...\n"\r
+                                I HAS value IZ $this->getRevisionUser()\r
+                               break;\r
+                       case 'namespace':\r
+                                I HAS value IZ str_replace( '_',' ',$wgContLang->getNsText( $this->mTitle->getNamespace() ) )\r
+                               break;\r
+                       case 'namespacee':\r
+                                I HAS value IZ wfUrlencode( $wgContLang->getNsText( $this->mTitle->getNamespace() ) )\r
+                               break;\r
+                       case 'talkspace':\r
+                                I HAS value IZ $this->mTitle->canTalk() ? str_replace( '_',' ',$this->mTitle->getTalkNsText() ) : ''\r
+                               break;\r
+                       case 'talkspacee':\r
+                                I HAS value IZ $this->mTitle->canTalk() ? wfUrlencode( $this->mTitle->getTalkNsText() ) : ''\r
+                               break;\r
+                       case 'subjectspace':\r
+                                I HAS value IZ $this->mTitle->getSubjectNsText()\r
+                               break;\r
+                       case 'subjectspacee':\r
+                                I HAS value IZ ( wfUrlencode( $this->mTitle->getSubjectNsText() ) )\r
+                               break;\r
+                       case 'currentdayname':\r
+                                I HAS value IZ $wgContLang->getWeekdayName( gmdate( 'w', $ts ) + 1 )\r
+                               break;\r
+                       case 'currentyear':\r
+                                I HAS value IZ $wgContLang->formatNum( gmdate( 'Y', $ts ), true )\r
+                               break;\r
+                       case 'currenttime':\r
+                                I HAS value IZ $wgContLang->time( wfTimestamp( TS_MW, $ts ), false, false )\r
+                               break;\r
+                       case 'currenthour':\r
+                                I HAS value IZ $wgContLang->formatNum( gmdate( 'H', $ts ), true )\r
+                               break;\r
+                       case 'currentweek':\r
+                                BTW @bug 4594 PHP5 has it zero padded, PHP4 does not, cast to\r
+                                BTW int to remove the padding\r
+                                I HAS value IZ $wgContLang->formatNum( (int)gmdate( 'W', $ts ) )\r
+                               break;\r
+                       case 'currentdow':\r
+                                I HAS value IZ $wgContLang->formatNum( gmdate( 'w', $ts ) )\r
+                               break;\r
+                       case 'localdayname':\r
+                                I HAS value IZ $wgContLang->getWeekdayName( $localDayOfWeek + 1 )\r
+                               break;\r
+                       case 'localyear':\r
+                                I HAS value IZ $wgContLang->formatNum( $localYear, true )\r
+                               break;\r
+                       case 'localtime':\r
+                                I HAS value IZ $wgContLang->time( $localTimestamp, false, false )\r
+                               break;\r
+                       case 'localhour':\r
+                                I HAS value IZ $wgContLang->formatNum( $localHour, true )\r
+                               break;\r
+                       case 'localweek':\r
+                                BTW @bug 4594 PHP5 has it zero padded, PHP4 does not, cast to\r
+                                BTW int to remove the padding\r
+                                I HAS value IZ $wgContLang->formatNum( (int)$localWeek )\r
+                               break;\r
+                       case 'localdow':\r
+                                I HAS value IZ $wgContLang->formatNum( $localDayOfWeek )\r
+                               break;\r
+                       case 'numberofarticles':\r
+                                I HAS value IZ $wgContLang->formatNum( SiteStats::articles() )\r
+                               break;\r
+                       case 'numberoffiles':\r
+                                I HAS value IZ $wgContLang->formatNum( SiteStats::images() )\r
+                               break;\r
+                       case 'numberofusers':\r
+                                I HAS value IZ $wgContLang->formatNum( SiteStats::users() )\r
+                               break;\r
+                       case 'numberofactiveusers':\r
+                                I HAS value IZ $wgContLang->formatNum( SiteStats::activeUsers() )\r
+                               break;\r
+                       case 'numberofpages':\r
+                                I HAS value IZ $wgContLang->formatNum( SiteStats::pages() )\r
+                               break;\r
+                       case 'numberofadmins':\r
+                                I HAS value IZ $wgContLang->formatNum( SiteStats::numberingroup( 'sysop' ) )\r
+                               break;\r
+                       case 'numberofedits':\r
+                                I HAS value IZ $wgContLang->formatNum( SiteStats::edits() )\r
+                               break;\r
+                       case 'numberofviews':\r
+                                I HAS value IZ $wgContLang->formatNum( SiteStats::views() )\r
+                               break;\r
+                       case 'currenttimestamp':\r
+                                I HAS value IZ wfTimestamp( TS_MW, $ts )\r
+                               break;\r
+                       case 'localtimestamp':\r
+                                I HAS value IZ $localTimestamp\r
+                               break;\r
+                       case 'currentversion':\r
+                                I HAS value IZ SpecialVersion::getVersion()\r
+                               break;\r
+                       case 'sitename':\r
+                                I FOUND MAH $wgSitename\r
+                       case 'server':\r
+                                I FOUND MAH $wgServer\r
+                       case 'servername':\r
+                                I FOUND MAH $wgServerName\r
+                       case 'scriptpath':\r
+                                I FOUND MAH $wgScriptPath\r
+                       case 'stylepath':\r
+                                I FOUND MAH $wgStylePath\r
+                       case 'directionmark':\r
+                                I FOUND MAH $wgContLang->getDirMark()\r
+                       case 'contentlanguage':\r
+                                I HAS UR $wgContLanguageCode ON UR INTERNETS\r
+                                I FOUND MAH $wgContLanguageCode\r
+                       default:\r
+                                I HAS ret\r
+                                IZ wfRunHooks( 'ParserGetVariableValueSwitch', array( &$this, &$this->mVarCache, &$index, &$ret, &$frame ) )\r
+                                        I FOUND MAH $ret\r
+                                NOWAI\r
+                                        I FOUND MAH null\r
+                                KTHX\r
+                KTHX\r
+\r
+               if ( $index )\r
+                       $this->mVarCache[$index] = $value;\r
+\r
+                I FOUND MAH $value\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT initialise the magic variables (like CURRENTMONTHNAME) and substitution modifiers \r
+         NOT WANT \r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE initialiseVariables\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+                I HAS variableIDs IZ MagicWord::getVariableIDs()\r
+                I HAS substIDs IZ MagicWord::getSubstIDs()\r
+\r
+                UR SPECIAL mVariables IZ new MagicWordArray( $variableIDs );\r
+                UR SPECIAL mSubstWords IZ new MagicWordArray( $substIDs );\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Preprocess some wikitext and return the document tree.\r
+         NOT WANT This is the ghost of replace_variables().\r
+         NOT WANT \r
+         NOT WANT @param string $text The text to parse\r
+         NOT WANT @param integer flags Bitwise combination of:\r
+         NOT WANT          self::PTD_FOR_INCLUSION    Handle <noinclude>/<includeonly> as if the text is being\r
+         NOT WANT                                     included. Default is to assume a direct page view.\r
+         NOT WANT \r
+         NOT WANT The generated DOM tree must depend only on the input text and the flags.\r
+         NOT WANT The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of bug 4899.\r
+         NOT WANT \r
+         NOT WANT Any flag added to the $flags parameter here, or any other parameter liable to cause a\r
+         NOT WANT change in the DOM tree for a given text, must be passed through the section identifier\r
+         NOT WANT in the section edit link and thus back to extractSections().\r
+         NOT WANT \r
+         NOT WANT The output of this function is currently only cached in process memory, but a persistent\r
+         NOT WANT cache may be implemented at a later date which takes further advantage of these strict\r
+         NOT WANT dependency requirements.\r
+         NOT WANT \r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE preprocessToDom WITH UR $text, $flags = 0\r
+                I HAS dom IZ $this->getPreprocessor()->preprocessToObj( $text, $flags )\r
+                I FOUND MAH $dom\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Return a three-element array: leading whitespace, string contents, trailing whitespace\r
+         WANT\r
+        SO IM ALWAYS LIKE splitWhitespace WITH UR $s\r
+                I HAS ltrimmed IZ ltrim( $s )\r
+                I HAS w1 IZ substr( $s, 0, strlen( $s ) - strlen( $ltrimmed ) )\r
+                I HAS trimmed IZ rtrim( $ltrimmed )\r
+                I HAS diff IZ strlen( $ltrimmed ) - strlen( $trimmed )\r
+                IZ $diff > 0\r
+                        I HAS w2 IZ substr( $ltrimmed, -$diff )\r
+                NOWAI\r
+                        I HAS w2 IZ ''\r
+                KTHX\r
+                I FOUND MAH array( $w1, $trimmed, $w2 )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Replace magic variables, templates, and template arguments\r
+         NOT WANT with the appropriate text. Templates are substituted recursively,\r
+         NOT WANT taking care to avoid infinite loops.\r
+         NOT WANT \r
+         NOT WANT Note that the substitution depends on value of $mOutputType:\r
+         NOT WANT  self::OT_WIKI: only {{subst:}} templates\r
+         NOT WANT  self::OT_PREPROCESS: templates but not extension tags\r
+         NOT WANT  self::OT_HTML: all templates and extension tags\r
+         NOT WANT \r
+         NOT WANT @param string $tex The text to transform\r
+         NOT WANT @param PPFrame $frame Object describing the arguments passed to the template.\r
+         NOT WANT        Arguments may also be provided as an associative array, as was the usual case before MW1.12.\r
+         NOT WANT        Providing arguments this way may be useful for extensions wishing to perform variable replacement explicitly.\r
+         NOT WANT @param bool $argsOnly Only do argument (triple-brace) expansion, not double-brace expansion\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE replaceVariables WITH UR $text, $frame = false, $argsOnly = false\r
+                BTW Is there any text? Also, Prevent too big inclusions!\r
+                IZ strlen( $text ) < 1 || strlen( $text ) > $this->mOptions->getMaxIncludeSize()\r
+                        I FOUND MAH $text\r
+                KTHX\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+\r
+                IZ $frame === false\r
+                        I HAS frame IZ $this->getPreprocessor()->newFrame()\r
+                ORLY !( $frame instanceof PPFrame )\r
+                        IM ON UR wfDebug DOING __METHOD__." called using plain parameters instead of a PPFrame instance. Creating custom frame.\n"\r
+                        I HAS frame IZ $this->getPreprocessor()->newCustomFrame( $frame )\r
+                KTHX\r
+\r
+                I HAS dom IZ $this->preprocessToDom( $text )\r
+                I HAS flags IZ $argsOnly ? PPFrame::NO_TEMPLATES : 0\r
+                I HAS text IZ $frame->expand( $dom, $flags )\r
+\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        BTW Clean up argument array - refactored in 1.9 so parserfunctions can use it, too.\r
+        SO IM ALWAYS LIKE createAssocArgs WITH UR $args\r
+                I HAS assocArgs IZ EMPTY\r
+                I HAS index IZ 1\r
+                IM IN UR args ITZA arg\r
+                        I HAS eqpos IZ strpos( $arg, '=' )\r
+                        IZ $eqpos === false\r
+                               $assocArgs[$index++] = $arg;\r
+                        NOWAI\r
+                                I HAS name IZ trim( substr( $arg, 0, $eqpos ) )\r
+                                I HAS value IZ trim( substr( $arg, $eqpos+1 ) )\r
+                                IZ $value === false\r
+                                        I HAS value IZ ''\r
+                                KTHX\r
+                                IZ $name !== false\r
+                                       $assocArgs[$name] = $value;\r
+                                KTHX\r
+                        KTHX\r
+                KTHX\r
+\r
+                I FOUND MAH $assocArgs\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Warn the user when a parser limitation is reached\r
+         NOT WANT Will warn at most once the user per limitation type\r
+         NOT WANT \r
+         NOT WANT @param string $limitationType, should be one of:\r
+         NOT WANT   'expensive-parserfunction' (corresponding messages: \r
+         NOT WANT       'expensive-parserfunction-warning', \r
+         NOT WANT       'expensive-parserfunction-category')\r
+         NOT WANT   'post-expand-template-argument' (corresponding messages: \r
+         NOT WANT       'post-expand-template-argument-warning', \r
+         NOT WANT       'post-expand-template-argument-category')\r
+         NOT WANT   'post-expand-template-inclusion' (corresponding messages: \r
+         NOT WANT       'post-expand-template-inclusion-warning', \r
+         NOT WANT       'post-expand-template-inclusion-category')\r
+         NOT WANT @params int $current, $max When an explicit limit has been\r
+         NOT WANT       exceeded, provide the values (optional)\r
+         WANT\r
+       function limitationWarn( $limitationType, $current=null, $max=null) {\r
+                BTW does no harm if $current and $max are present but are unnecessary for the message\r
+                I HAS warning IZ wfMsgExt( "$limitationType-warning", array( 'parsemag', 'escape' ), $current, $max )\r
+                IM ON UR SPECIAL mOutput->addWarning DOING $warning\r
+                IM ON UR SPECIAL addTrackingCategory DOING "$limitationType-category"\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Return the text of a template, after recursively\r
+         NOT WANT replacing any variables or templates within the template.\r
+         NOT WANT \r
+         NOT WANT @param array $piece The parts of the template\r
+         NOT WANT  $piece['title']: the title, i.e. the part before the |\r
+         NOT WANT  $piece['parts']: the parameter array\r
+         NOT WANT  $piece['lineStart']: whether the brace was at the start of a line\r
+         NOT WANT @param PPFrame The current frame, contains template arguments\r
+         NOT WANT @return string the text of the template\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE braceSubstitution WITH UR $piece, $frame\r
+                I HAS UR $wgContLang, $wgNonincludableNamespaces ON UR INTERNETS\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+                IM ON UR wfProfileIn DOING __METHOD__.'-setup'\r
+\r
+                BTW Flags\r
+                I HAS found IZ false             # $text has been filled\r
+                I HAS nowiki IZ false            # wiki markup in $text should be escaped\r
+                I HAS isHTML IZ false            # $text is HTML, armour it against wikitext transformation\r
+                I HAS forceRawInterwiki IZ false # Force interwiki transclusion to be done in raw mode not rendered\r
+                I HAS isChildObj IZ false        # $text is a DOM node needing expansion in a child frame\r
+                I HAS isLocalObj IZ false        # $text is a DOM node needing expansion in the current frame\r
+\r
+                BTW Title object, where $text came from\r
+                I HAS title\r
+\r
+                BTW $part1 is the bit before the first |, and must contain only title characters.\r
+                BTW Various prefixes will be stripped from it later.\r
+                I HAS titleWithSpaces IZ $frame->expand( $piece['title'] )\r
+                I HAS part1 IZ trim( $titleWithSpaces )\r
+                I HAS titleText IZ false\r
+\r
+                BTW Original title text preserved for various purposes\r
+                I HAS originalTitle IZ $part1\r
+\r
+                BTW $args is a list of argument nodes, starting from index 0, not including $part1\r
+                I HAS args IZ ( null == $piece['parts'] ) ? array() : $piece['parts']\r
+                IM ON UR wfProfileOut DOING __METHOD__.'-setup'\r
+\r
+                BTW SUBST\r
+                IM ON UR wfProfileIn DOING __METHOD__.'-modifiers'\r
+                IZ !$found\r
+\r
+                        I HAS substMatch IZ $this->mSubstWords->matchStartAndRemove( $part1 )\r
+\r
+                        BTW Possibilities for substMatch: "subst", "safesubst" or FALSE\r
+                        BTW Decide whether to expand template or keep wikitext as-is.\r
+                        IZ $this->ot['wiki']\r
+                                IZ $substMatch === false\r
+                                        I HAS literal IZ true  # literal when in PST with no prefix\r
+                                NOWAI\r
+                                        I HAS literal IZ false # expand when in PST with subst: or safesubst:\r
+                                KTHX\r
+                        NOWAI\r
+                                IZ $substMatch == 'subst'\r
+                                        I HAS literal IZ true  # literal when not in PST with plain subst:\r
+                                NOWAI\r
+                                        I HAS literal IZ false # expand when not in PST with safesubst: or no prefix\r
+                                KTHX\r
+                        KTHX\r
+                        IZ $literal\r
+                                I HAS text IZ $frame->virtualBracketedImplode( '{{', '|', '}}', $titleWithSpaces, $args )\r
+                                I HAS isLocalObj IZ true\r
+                                I HAS found IZ true\r
+                        KTHX\r
+                KTHX\r
+\r
+                BTW Variables\r
+                IZ !$found && $args->getLength() == 0\r
+                        I HAS id IZ $this->mVariables->matchStartToEnd( $part1 )\r
+                        IZ $id !== false\r
+                                I HAS text IZ $this->getVariableValue( $id, $frame )\r
+                                IZ MagicWord::getCacheTTL( $id ) > -1\r
+                                        UR SPECIAL mOutput->mContainsOldMagic IZ true;\r
+                                KTHX\r
+                                I HAS found IZ true\r
+                        KTHX\r
+                KTHX\r
+\r
+                BTW MSG, MSGNW and RAW\r
+                IZ !$found\r
+                        BTW Check for MSGNW:\r
+                        I HAS mwMsgnw IZ MagicWord::get( 'msgnw' )\r
+                        IZ $mwMsgnw->matchStartAndRemove( $part1 )\r
+                                I HAS nowiki IZ true\r
+                        NOWAI\r
+                                BTW Remove obsolete MSG:\r
+                                I HAS mwMsg IZ MagicWord::get( 'msg' )\r
+                               $mwMsg->matchStartAndRemove( $part1 );\r
+                        KTHX\r
+\r
+                        BTW Check for RAW:\r
+                        I HAS mwRaw IZ MagicWord::get( 'raw' )\r
+                        IZ $mwRaw->matchStartAndRemove( $part1 )\r
+                                I HAS forceRawInterwiki IZ true\r
+                        KTHX\r
+                KTHX\r
+                IM ON UR wfProfileOut DOING __METHOD__.'-modifiers'\r
+\r
+                BTW Parser functions\r
+                IZ !$found\r
+                        IM ON UR wfProfileIn DOING __METHOD__ . '-pfunc'\r
+\r
+                        I HAS colonPos IZ strpos( $part1, ':' )\r
+                        IZ $colonPos !== false\r
+                                BTW Case sensitive functions\r
+                                I HAS function IZ substr( $part1, 0, $colonPos )\r
+                                IZ isset( $this->mFunctionSynonyms[1][$function] )\r
+                                        I HAS function IZ $this->mFunctionSynonyms[1][$function]\r
+                                NOWAI\r
+                                        BTW Case insensitive functions\r
+                                        I HAS function IZ $wgContLang->lc( $function )\r
+                                        IZ isset( $this->mFunctionSynonyms[0][$function] )\r
+                                                I HAS function IZ $this->mFunctionSynonyms[0][$function]\r
+                                        NOWAI\r
+                                                I HAS function IZ false\r
+                                        KTHX\r
+                                KTHX\r
+                                IZ $function\r
+                                       list( $callback, $flags ) = $this->mFunctionHooks[$function];\r
+                                        I HAS initialArgs IZ BUCKET &$this );\r
+                                        I HAS funcArgs IZ BUCKET trim( substr( $part1, $colonPos + 1 ) ) );\r
+                                        IZ $flags & SFH_OBJECT_ARGS\r
+                                                BTW Add a frame parameter, and pass the arguments as an array\r
+                                                I HAS allArgs IZ $initialArgs\r
+                                               $allArgs[] = $frame;\r
+                                               for ( $i = 0; $i < $args->getLength(); $i++ ) {\r
+                                                       $funcArgs[] = $args->item( $i );\r
+                                                KTHX\r
+                                               $allArgs[] = $funcArgs;\r
+                                        NOWAI\r
+                                                BTW Convert arguments to plain text\r
+                                               for ( $i = 0; $i < $args->getLength(); $i++ ) {\r
+                                                       $funcArgs[] = trim( $frame->expand( $args->item( $i ) ) );\r
+                                                KTHX\r
+                                                I HAS allArgs IZ array_merge( $initialArgs, $funcArgs )\r
+                                        KTHX\r
+\r
+                                        BTW Workaround for PHP bug 35229 and similar\r
+                                        IZ !is_callable( $callback )\r
+                                                IM ON UR wfProfileOut DOING __METHOD__ . '-pfunc'\r
+                                                IM ON UR wfProfileOut DOING __METHOD__\r
+                                               throw new MWException( "Tag hook for $function is not callable\n" );\r
+                                        KTHX\r
+                                        I HAS result IZ call_user_func_array( $callback, $allArgs )\r
+                                        I HAS found IZ true\r
+                                        I HAS noparse IZ true\r
+                                        I HAS preprocessFlags IZ 0\r
+\r
+                                        IZ is_array( $result )\r
+                                                IZ isset( $result[0] )\r
+                                                        I HAS text IZ $result[0]\r
+                                                        IM ON UR unset DOING $result[0]\r
+                                                KTHX\r
+\r
+                                                BTW Extract flags into the local scope\r
+                                                BTW This allows callers to set flags such as nowiki, found, etc.\r
+                                                IM ON UR extract DOING $result\r
+                                        NOWAI\r
+                                                I HAS text IZ $result\r
+                                        KTHX\r
+                                        IZ !$noparse\r
+                                                I HAS text IZ $this->preprocessToDom( $text, $preprocessFlags )\r
+                                                I HAS isChildObj IZ true\r
+                                        KTHX\r
+                                KTHX\r
+                        KTHX\r
+                        IM ON UR wfProfileOut DOING __METHOD__ . '-pfunc'\r
+                KTHX\r
+\r
+                BTW Finish mangling title and then check for loops.\r
+                BTW Set $title to a Title object and $titleText to the PDBK\r
+                IZ !$found\r
+                        I HAS ns IZ NS_TEMPLATE\r
+                        BTW Split the title into page and subpage\r
+                        I HAS subpage IZ ''\r
+                        I HAS part1 IZ $this->maybeDoSubpageLink( $part1, $subpage )\r
+                        IZ $subpage !== ''\r
+                                I HAS ns IZ $this->mTitle->getNamespace()\r
+                        KTHX\r
+                        I HAS title IZ Title::newFromText( $part1, $ns )\r
+                        IZ $title\r
+                                I HAS titleText IZ $title->getPrefixedText()\r
+                                BTW Check for language variants if the template is not found\r
+                                IZ $wgContLang->hasVariants() && $title->getArticleID() == 0\r
+                                       $wgContLang->findVariantLink( $part1, $title, true );\r
+                                KTHX\r
+                                BTW Do recursion depth check\r
+                                I HAS limit IZ $this->mOptions->getMaxTemplateDepth()\r
+                                IZ $frame->depth >= $limit\r
+                                        I HAS found IZ true\r
+                                        text IZ '<span class="error">' \r
+                                               . wfMsgForContent( 'parser-template-recursion-depth-warning', $limit ) \r
+                                               . '</span>';\r
+                                KTHX\r
+                        KTHX\r
+                KTHX\r
+\r
+                BTW Load from database\r
+                IZ !$found && $title\r
+                        IM ON UR wfProfileIn DOING __METHOD__ . '-loadtpl'\r
+                        IZ !$title->isExternal()\r
+                               if ( $title->getNamespace() == NS_SPECIAL \r
+                                       && $this->mOptions->getAllowSpecialInclusion() \r
+                                       && $this->ot['html'] ) \r
+                               {\r
+                                        I HAS text IZ SpecialPage::capturePath( $title )\r
+                                        IZ is_string( $text )\r
+                                                I HAS found IZ true\r
+                                                I HAS isHTML IZ true\r
+                                                IM ON UR SPECIAL disableCache\r
+                                        KTHX\r
+                                ORLY $wgNonincludableNamespaces && in_array( $title->getNamespace(), $wgNonincludableNamespaces )\r
+                                        I HAS found IZ false # access denied\r
+                                        IM ON UR wfDebug DOING __METHOD__.": template inclusion denied for " . $title->getPrefixedDBkey()\r
+                                NOWAI\r
+                                        IM ON UR list DOING $text, $title ) = $this->getTemplateDom( $title\r
+                                        IZ $text !== false\r
+                                                I HAS found IZ true\r
+                                                I HAS isChildObj IZ true\r
+                                        KTHX\r
+                                KTHX\r
+\r
+                                BTW If the title is valid but undisplayable, make a link to it\r
+                                IZ !$found && ( $this->ot['html'] || $this->ot['pre'] )\r
+                                        I HAS text IZ "[[:$titleText]]"\r
+                                        I HAS found IZ true\r
+                                KTHX\r
+                        ORLY $title->isTrans()\r
+                                BTW Interwiki transclusion\r
+                                IZ $this->ot['html'] && !$forceRawInterwiki\r
+                                        I HAS text IZ $this->interwikiTransclude( $title, 'render' )\r
+                                        I HAS isHTML IZ true\r
+                                NOWAI\r
+                                        I HAS text IZ $this->interwikiTransclude( $title, 'raw' )\r
+                                        BTW Preprocess it like a template\r
+                                        I HAS text IZ $this->preprocessToDom( $text, self::PTD_FOR_INCLUSION )\r
+                                        I HAS isChildObj IZ true\r
+                                KTHX\r
+                                I HAS found IZ true\r
+                        KTHX\r
+\r
+                        BTW Do infinite loop check\r
+                        BTW This has to be done after redirect resolution to avoid infinite loops via redirects\r
+                        IZ !$frame->loopCheck( $title )\r
+                                I HAS found IZ true\r
+                                I HAS text IZ '<span class="error">' . wfMsgForContent( 'parser-template-loop-warning', $titleText ) . '</span>'\r
+                                IM ON UR wfDebug DOING __METHOD__.": template loop broken at '$titleText'\n"\r
+                        KTHX\r
+                        IM ON UR wfProfileOut DOING __METHOD__ . '-loadtpl'\r
+                KTHX\r
+\r
+                BTW If we haven't found text to substitute by now, we're done\r
+                BTW Recover the source wikitext and return it\r
+                IZ !$found\r
+                        I HAS text IZ $frame->virtualBracketedImplode( '{{', '|', '}}', $titleWithSpaces, $args )\r
+                        IM ON UR wfProfileOut DOING __METHOD__\r
+                        I FOUND MAH array( 'object' => $text )\r
+                KTHX\r
+\r
+                BTW Expand DOM-style return values in a child frame\r
+                IZ $isChildObj\r
+                        BTW Clean up argument array\r
+                        I HAS newFrame IZ $frame->newChild( $args, $title )\r
+\r
+                        IZ $nowiki\r
+                                I HAS text IZ $newFrame->expand( $text, PPFrame::RECOVER_ORIG )\r
+                        ORLY $titleText !== false && $newFrame->isEmpty()\r
+                                BTW Expansion is eligible for the empty-frame cache\r
+                                IZ isset( $this->mTplExpandCache[$titleText] )\r
+                                        I HAS text IZ $this->mTplExpandCache[$titleText]\r
+                                NOWAI\r
+                                        I HAS text IZ $newFrame->expand( $text )\r
+                                       $this->mTplExpandCache[$titleText] = $text;\r
+                                KTHX\r
+                        NOWAI\r
+                                BTW Uncached expansion\r
+                                I HAS text IZ $newFrame->expand( $text )\r
+                        KTHX\r
+                KTHX\r
+                IZ $isLocalObj && $nowiki\r
+                        I HAS text IZ $frame->expand( $text, PPFrame::RECOVER_ORIG )\r
+                        I HAS isLocalObj IZ false\r
+                KTHX\r
+\r
+                BTW Replace raw HTML by a placeholder\r
+                BTW Add a blank line preceding, to prevent it from mucking up\r
+                BTW immediately preceding headings\r
+                IZ $isHTML\r
+                        I HAS text IZ "\n\n" . $this->insertStripItem( $text )\r
+                ORLY $nowiki && ( $this->ot['html'] || $this->ot['pre'] )\r
+                        BTW Escape nowiki-style return values\r
+                        I HAS text IZ wfEscapeWikiText( $text )\r
+                KTHX elseif ( is_string( $text )\r
+                       && !$piece['lineStart'] \r
+                       && preg_match( '/^(?:{\\||:|;|#|\*)/', $text ) )\r
+               {\r
+                        BTW Bug 529: if the template begins with a table or block-level\r
+                        BTW element, it should be treated as beginning a new line.\r
+                        BTW This behaviour is somewhat controversial.\r
+                        I HAS text IZ "\n" . $text\r
+                KTHX\r
+\r
+                IZ is_string( $text ) && !$this->incrementIncludeSize( 'post-expand', strlen( $text ) )\r
+                        BTW Error, oversize inclusion\r
+                        text IZ "[[$originalTitle]]" .\r
+                                IM ON UR SPECIAL insertStripItem DOING '<!-- WARNING: template omitted, post-expand include size too large -->'\r
+                        IM ON UR SPECIAL limitationWarn DOING 'post-expand-template-inclusion'\r
+                KTHX\r
+\r
+                IZ $isLocalObj\r
+                        I HAS ret IZ BUCKET 'object' => $text );\r
+                NOWAI\r
+                        I HAS ret IZ BUCKET 'text' => $text );\r
+                KTHX\r
+\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $ret\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Get the semi-parsed DOM representation of a template with a given title,\r
+         NOT WANT and its redirect destination title. Cached.\r
+         WANT\r
+        SO IM LIKE getTemplateDom WITH UR $title\r
+                I HAS cacheTitle IZ $title\r
+                I HAS titleText IZ $title->getPrefixedDBkey()\r
+\r
+                IZ isset( $this->mTplRedirCache[$titleText] )\r
+                       list( $ns, $dbk ) = $this->mTplRedirCache[$titleText];\r
+                        I HAS title IZ Title::makeTitle( $ns, $dbk )\r
+                        I HAS titleText IZ $title->getPrefixedDBkey()\r
+                KTHX\r
+                IZ isset( $this->mTplDomCache[$titleText] )\r
+                        I FOUND MAH array( $this->mTplDomCache[$titleText], $title )\r
+                KTHX\r
+\r
+                BTW Cache miss, go to the database\r
+                IM ON UR list DOING $text, $title ) = $this->fetchTemplateAndTitle( $title\r
+\r
+                IZ $text === false\r
+                       $this->mTplDomCache[$titleText] = false;\r
+                        I FOUND MAH array( false, $title )\r
+                KTHX\r
+\r
+                I HAS dom IZ $this->preprocessToDom( $text, self::PTD_FOR_INCLUSION )\r
+               $this->mTplDomCache[ $titleText ] = $dom;\r
+\r
+                IZ !$title->equals( $cacheTitle )\r
+                       $this->mTplRedirCache[$cacheTitle->getPrefixedDBkey()] =\r
+                                IM ON UR array DOING $title->getNamespace(),$cdb = $title->getDBkey()\r
+                KTHX\r
+\r
+                I FOUND MAH array( $dom, $title )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Fetch the unparsed text of a template and register a reference to it.\r
+         WANT\r
+        SO IM LIKE fetchTemplateAndTitle WITH UR $title\r
+                I HAS templateCb IZ $this->mOptions->getTemplateCallback()\r
+                I HAS stuff IZ call_user_func( $templateCb, $title, $this )\r
+                I HAS text IZ $stuff['text']\r
+                I HAS finalTitle IZ isset( $stuff['finalTitle'] ) ? $stuff['finalTitle'] : $title\r
+                IZ isset( $stuff['deps'] )\r
+                       foreach ( $stuff['deps'] as $dep ) {\r
+                                IM ON UR SPECIAL mOutput->addTemplate DOING $dep['title'], $dep['page_id'], $dep['rev_id']\r
+                        KTHX\r
+                KTHX\r
+                I FOUND MAH array( $text, $finalTitle )\r
+        KTHX\r
+\r
+        SO IM LIKE fetchTemplate WITH UR $title\r
+                I HAS rv IZ $this->fetchTemplateAndTitle( $title )\r
+                I FOUND MAH $rv[0]\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Static function to get a template\r
+         NOT WANT Can be overridden via ParserOptions::setTemplateCallback().\r
+         WANT\r
+        SO IM ALWAYS LIKE statelessFetchTemplate WITH UR $title, $parser=false\r
+                I HAS text IZ $skip = false\r
+                I HAS finalTitle IZ $title\r
+                I HAS deps IZ EMPTY\r
+\r
+                BTW Loop to fetch the article, with up to 1 redirect\r
+               for ( $i = 0; $i < 2 && is_object( $title ); $i++ ) {\r
+                        BTW Give extensions a chance to select the revision instead\r
+                        I HAS id IZ false # Assume current\r
+                        IM ON UR wfRunHooks DOING 'BeforeParserFetchTemplateAndtitle', array( $parser, &$title, &$skip, &$id )\r
+\r
+                        IZ $skip\r
+                                I HAS text IZ false\r
+                               $deps[] = array(\r
+                                       'title' => $title,\r
+                                       'page_id' => $title->getArticleID(),\r
+                                       'rev_id' => null );\r
+                               break;\r
+                        KTHX\r
+                        I HAS rev IZ $id ? Revision::newFromId( $id ) : Revision::newFromTitle( $title )\r
+                        I HAS rev_id IZ $rev ? $rev->getId() : 0\r
+                        BTW If there is no current revision, there is no page\r
+                        IZ $id === false && !$rev\r
+                                I HAS linkCache IZ LinkCache::singleton()\r
+                               $linkCache->addBadLinkObj( $title );\r
+                        KTHX\r
+\r
+                       $deps[] = array(\r
+                               'title' => $title,\r
+                               'page_id' => $title->getArticleID(),\r
+                               'rev_id' => $rev_id );\r
+\r
+                        IZ $rev\r
+                                I HAS text IZ $rev->getText()\r
+                        ORLY $title->getNamespace() == NS_MEDIAWIKI\r
+                                I HAS UR $wgContLang ON UR INTERNETS\r
+                                I HAS message IZ $wgContLang->lcfirst( $title->getText() )\r
+                                I HAS text IZ wfMsgForContentNoTrans( $message )\r
+                                IZ wfEmptyMsg( $message, $text )\r
+                                        I HAS text IZ false\r
+                                       break;\r
+                                KTHX\r
+                        NOWAI\r
+                               break;\r
+                        KTHX\r
+                        IZ $text === false\r
+                               break;\r
+                        KTHX\r
+                        BTW Redirect?\r
+                        I HAS finalTitle IZ $title\r
+                        I HAS title IZ Title::newFromRedirect( $text )\r
+                KTHX\r
+               return array(\r
+                       'text' => $text,\r
+                       'finalTitle' => $finalTitle,\r
+                       'deps' => $deps );\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Transclude an interwiki link.\r
+         WANT\r
+        SO IM LIKE interwikiTransclude WITH UR $title, $action\r
+                I HAS UR $wgEnableScaryTranscluding ON UR INTERNETS\r
+\r
+                IZ !$wgEnableScaryTranscluding\r
+                        I FOUND MAH wfMsg('scarytranscludedisabled')\r
+                KTHX\r
+\r
+                I HAS url IZ $title->getFullUrl( "action=$action" )\r
+\r
+                IZ strlen( $url ) > 255\r
+                        I FOUND MAH wfMsg( 'scarytranscludetoolong' )\r
+                KTHX\r
+                I FOUND MAH $this->fetchScaryTemplateMaybeFromCache( $url )\r
+        KTHX\r
+\r
+        SO IM LIKE fetchScaryTemplateMaybeFromCache WITH UR $url\r
+                I HAS UR $wgTranscludeCacheExpiry ON UR INTERNETS\r
+                I HAS dbr IZ wfGetDB( DB_SLAVE )\r
+                I HAS tsCond IZ $dbr->timestamp( time() - $wgTranscludeCacheExpiry )\r
+                obj IZ $dbr->selectRow( 'transcache', array('tc_time', 'tc_contents' ),\r
+                                IM ON UR array DOING 'tc_url' => $url, "tc_time >= " . $dbr->addQuotes( $tsCond ) )\r
+                IZ $obj\r
+                        I FOUND MAH $obj->tc_contents\r
+                KTHX\r
+\r
+                I HAS text IZ Http::get( $url )\r
+                IZ !$text\r
+                        I FOUND MAH wfMsg( 'scarytranscludefailed', $url )\r
+                KTHX\r
+\r
+                I HAS dbw IZ wfGetDB( DB_MASTER )\r
+               $dbw->replace( 'transcache', array('tc_url'), array(\r
+                       'tc_url' => $url,\r
+                       'tc_time' => $dbw->timestamp( time() ),\r
+                       'tc_contents' => $text)\r
+                BUCKET\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+\r
+        DO NOT WANT\r
+         NOT WANT Triple brace replacement -- used for template arguments\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE argSubstitution WITH UR $piece, $frame\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+\r
+                I HAS error IZ false\r
+                I HAS parts IZ $piece['parts']\r
+                I HAS nameWithSpaces IZ $frame->expand( $piece['title'] )\r
+                I HAS argName IZ trim( $nameWithSpaces )\r
+                I HAS object IZ false\r
+                I HAS text IZ $frame->getArgument( $argName )\r
+               if (  $text === false && $parts->getLength() > 0\r
+                 && (\r
+                   $this->ot['html']\r
+                   || $this->ot['pre']\r
+                   || ( $this->ot['wiki'] && $frame->isTemplate() )\r
+                 )\r
+               ) {\r
+                        BTW No match in frame, use the supplied default\r
+                        I HAS object IZ $parts->item( 0 )->getChildren()\r
+                KTHX\r
+                IZ !$this->incrementIncludeSize( 'arg', strlen( $text ) )\r
+                        I HAS error IZ '<!-- WARNING: argument omitted, expansion size too large -->'\r
+                        IM ON UR SPECIAL limitationWarn DOING 'post-expand-template-argument'\r
+                KTHX\r
+\r
+                IZ $text === false && $object === false\r
+                        BTW No match anywhere\r
+                        I HAS object IZ $frame->virtualBracketedImplode( '{{{', '|', '}}}', $nameWithSpaces, $parts )\r
+                KTHX\r
+                IZ $error !== false\r
+                        text HAS MOAR $error;\r
+                KTHX\r
+                IZ $object !== false\r
+                        I HAS ret IZ BUCKET 'object' => $object );\r
+                NOWAI\r
+                        I HAS ret IZ BUCKET 'text' => $text );\r
+                KTHX\r
+\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $ret\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Return the text to be used for a given extension tag.\r
+         NOT WANT This is the ghost of strip().\r
+         NOT WANT \r
+         NOT WANT @param array $params Associative array of parameters:\r
+         NOT WANT     name       PPNode for the tag name\r
+         NOT WANT     attr       PPNode for unparsed text where tag attributes are thought to be\r
+         NOT WANT     attributes Optional associative array of parsed attributes\r
+         NOT WANT     inner      Contents of extension element\r
+         NOT WANT     noClose    Original text did not have a close tag\r
+         NOT WANT @param PPFrame $frame\r
+         WANT\r
+        SO IM LIKE extensionSubstitution WITH UR $params, $frame\r
+                I HAS UR $wgRawHtml, $wgContLang ON UR INTERNETS\r
+\r
+                I HAS name IZ $frame->expand( $params['name'] )\r
+                I HAS attrText IZ !isset( $params['attr'] ) ? null : $frame->expand( $params['attr'] )\r
+                I HAS content IZ !isset( $params['inner'] ) ? null : $frame->expand( $params['inner'] )\r
+                I HAS marker IZ "{$this->mUniqPrefix}-$name-" . sprintf( '%08X', $this->mMarkerIndex++ ) . self::MARKER_SUFFIX\r
+\r
+                isFunctionTag IZ isset( $this->mFunctionTagHooks[strtolower($name)] ) &&\r
+                       ( $this->ot['html'] || $this->ot['pre'] );\r
+                IZ $isFunctionTag\r
+                        I HAS markerType IZ 'none'\r
+                NOWAI\r
+                        I HAS markerType IZ 'general'\r
+                KTHX\r
+                IZ $this->ot['html'] || $isFunctionTag\r
+                        I HAS name IZ strtolower( $name )\r
+                        I HAS attributes IZ Sanitizer::decodeTagAttributes( $attrText )\r
+                        IZ isset( $params['attributes'] )\r
+                                I HAS attributes IZ $attributes + $params['attributes']\r
+                        KTHX\r
+\r
+                        IZ isset( $this->mTagHooks[$name] )\r
+                                BTW Workaround for PHP bug 35229 and similar\r
+                                IZ !is_callable( $this->mTagHooks[$name] )\r
+                                       throw new MWException( "Tag hook for $name is not callable\n" );\r
+                                KTHX\r
+                                output IZ call_user_func_array( $this->mTagHooks[$name],\r
+                                        IM ON UR array DOING $content, $attributes, $this, $frame )\r
+                        ORLY isset( $this->mFunctionTagHooks[$name] )\r
+                               list( $callback, $flags ) = $this->mFunctionTagHooks[$name];\r
+                                IZ !is_callable( $callback )\r
+                                       throw new MWException( "Tag hook for $name is not callable\n" );\r
+                                KTHX\r
+\r
+                                I HAS output IZ call_user_func_array( $callback, array( &$this, $frame, $content, $attributes ) )\r
+                        NOWAI\r
+                                output IZ '<span class="error">Invalid tag extension name: ' .\r
+                                       htmlspecialchars( $name ) . '</span>';\r
+                        KTHX\r
+\r
+                        IZ is_array( $output )\r
+                                BTW Extract flags to local scope (to override $markerType)\r
+                                I HAS flags IZ $output\r
+                                I HAS output IZ $flags[0]\r
+                                IM ON UR unset DOING $flags[0]\r
+                                IM ON UR extract DOING $flags\r
+                        KTHX\r
+                NOWAI\r
+                        IZ is_null( $attrText )\r
+                                I HAS attrText IZ ''\r
+                        KTHX\r
+                        IZ isset( $params['attributes'] )\r
+                               foreach ( $params['attributes'] as $attrName => $attrValue ) {\r
+                                        attrText HAS MOAR ' ' . htmlspecialchars( $attrName ) . '="' .\r
+                                               htmlspecialchars( $attrValue ) . '"';\r
+                                KTHX\r
+                        KTHX\r
+                        IZ $content === null\r
+                                I HAS output IZ "<$name$attrText/>"\r
+                        NOWAI\r
+                                I HAS close IZ is_null( $params['close'] ) ? '' : $frame->expand( $params['close'] )\r
+                                I HAS output IZ "<$name$attrText>$content$close"\r
+                        KTHX\r
+                KTHX\r
+\r
+                IZ $markerType === 'none'\r
+                        I FOUND MAH $output\r
+                ORLY $markerType === 'nowiki'\r
+                        IM ON UR SPECIAL mStripState->nowiki->setPair DOING $marker, $output\r
+                ORLY $markerType === 'general'\r
+                        IM ON UR SPECIAL mStripState->general->setPair DOING $marker, $output\r
+                NOWAI\r
+                       throw new MWException( __METHOD__.': invalid marker type' );\r
+                KTHX\r
+                I FOUND MAH $marker\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Increment an include size counter\r
+         NOT WANT \r
+         NOT WANT @param string $type The type of expansion\r
+         NOT WANT @param integer $size The size of the text\r
+         NOT WANT @return boolean False if this inclusion would take it over the maximum, true otherwise\r
+         WANT\r
+        SO IM LIKE incrementIncludeSize WITH UR $type, $size\r
+                IZ $this->mIncludeSizes[$type] + $size > $this->mOptions->getMaxIncludeSize( $type )\r
+                        I FOUND MAH false\r
+                NOWAI\r
+                       $this->mIncludeSizes[$type] += $size;\r
+                        I FOUND MAH true\r
+                KTHX\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Increment the expensive function count\r
+         NOT WANT \r
+         NOT WANT @return boolean False if the limit has been exceeded\r
+         WANT\r
+        SO IM LIKE incrementExpensiveFunctionCount\r
+                I HAS UR $wgExpensiveParserFunctionLimit ON UR INTERNETS\r
+               $this->mExpensiveFunctionCount++;\r
+                IZ $this->mExpensiveFunctionCount <= $wgExpensiveParserFunctionLimit\r
+                        I FOUND MAH true\r
+                KTHX\r
+                I FOUND MAH false\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Strip double-underscore items like __NOGALLERY__ and __NOTOC__\r
+         NOT WANT Fills $this->mDoubleUnderscores, returns the modified text\r
+         WANT\r
+        SO IM LIKE doDoubleUnderscore WITH UR $text\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+\r
+                BTW The position of __TOC__ needs to be recorded\r
+                I HAS mw IZ MagicWord::get( 'toc' )\r
+                IZ $mw->match( $text )\r
+                        UR SPECIAL mShowToc IZ true;\r
+                        UR SPECIAL mForceTocPosition IZ true;\r
+\r
+                        BTW Set a placeholder. At the end we'll fill it in with the TOC.\r
+                        I HAS text IZ $mw->replace( '<!--MWTOC-->', $text, 1 )\r
+\r
+                        BTW Only keep the first one.\r
+                        I HAS text IZ $mw->replace( '', $text )\r
+                KTHX\r
+\r
+                BTW Now match and remove the rest of them\r
+                I HAS mwa IZ MagicWord::getDoubleUnderscoreArray()\r
+                UR SPECIAL mDoubleUnderscores IZ $mwa->matchAndRemove( $text );\r
+\r
+                IZ isset( $this->mDoubleUnderscores['nogallery'] )\r
+                        UR SPECIAL mOutput->mNoGallery IZ true;\r
+                KTHX\r
+                IZ isset( $this->mDoubleUnderscores['notoc'] ) && !$this->mForceTocPosition\r
+                        UR SPECIAL mShowToc IZ false;\r
+                KTHX\r
+                IZ isset( $this->mDoubleUnderscores['hiddencat'] ) && $this->mTitle->getNamespace() == NS_CATEGORY\r
+                        IM ON UR SPECIAL mOutput->setProperty DOING 'hiddencat', 'y'\r
+                        IM ON UR SPECIAL addTrackingCategory DOING 'hidden-category-category'\r
+                KTHX\r
+                BTW (bug 8068) Allow control over whether robots index a page.\r
+                BTW \r
+                BTW FIXME (bug 14899): __INDEX__ always overrides __NOINDEX__ here!  This\r
+                BTW is not desirable, the last one on the page should win.\r
+                IZ isset( $this->mDoubleUnderscores['noindex'] ) && $this->mTitle->canUseNoindex()\r
+                        IM ON UR SPECIAL mOutput->setIndexPolicy DOING 'noindex'\r
+                        IM ON UR SPECIAL addTrackingCategory DOING 'noindex-category'\r
+                KTHX\r
+                IZ isset( $this->mDoubleUnderscores['index'] ) && $this->mTitle->canUseNoindex()\r
+                        IM ON UR SPECIAL mOutput->setIndexPolicy DOING 'index'\r
+                        IM ON UR SPECIAL addTrackingCategory DOING 'index-category'\r
+                KTHX\r
+\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Add a tracking category, getting the title from a system message,\r
+         NOT WANT or print a debug message if the title is invalid.\r
+         NOT WANT @param $msg String message key\r
+         NOT WANT @return Bool whether the addition was successful\r
+         WANT\r
+        SO IM LIKE addTrackingCategory WITH UR $msg\r
+                I HAS cat IZ wfMsgForContent( $msg )\r
+\r
+                BTW Allow tracking categories to be disabled by setting them to "-"\r
+                IZ $cat === '-'\r
+                        I FOUND MAH false\r
+                KTHX\r
+\r
+                I HAS containerCategory IZ Title::makeTitleSafe( NS_CATEGORY, $cat )\r
+                IZ $containerCategory\r
+                        IM ON UR SPECIAL mOutput->addCategory DOING $containerCategory->getDBkey(), $this->getDefaultSort()\r
+                        I FOUND MAH true\r
+                NOWAI\r
+                        IM ON UR wfDebug DOING __METHOD__.": [[MediaWiki:$msg]] is not a valid title!\n"\r
+                        I FOUND MAH false\r
+                KTHX\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT This function accomplishes several tasks:\r
+         NOT WANT 1) Auto-number headings if that option is enabled\r
+         NOT WANT 2) Add an [edit] link to sections for users who have enabled the option and can edit the page\r
+         NOT WANT 3) Add a Table of contents on the top for users who have enabled the option\r
+         NOT WANT 4) Auto-anchor headings\r
+         NOT WANT \r
+         NOT WANT It loops through all headlines, collects the necessary data, then splits up the\r
+         NOT WANT string and re-inserts the newly formatted headlines.\r
+         NOT WANT \r
+         NOT WANT @param string $text\r
+         NOT WANT @param string $origText Original, untouched wikitext\r
+         NOT WANT @param boolean $isMain\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE formatHeadings WITH UR $text, $origText, $isMain=true\r
+                I HAS UR $wgMaxTocLevel, $wgContLang, $wgHtml5, $wgExperimentalHtmlIds ON UR INTERNETS\r
+\r
+                I HAS doNumberHeadings IZ $this->mOptions->getNumberHeadings()\r
+                I HAS showEditLink IZ $this->mOptions->getEditSection()\r
+\r
+                BTW Do not call quickUserCan unless necessary\r
+                IZ $showEditLink && !$this->mTitle->quickUserCan( 'edit' )\r
+                        I HAS showEditLink IZ 0\r
+                KTHX\r
+\r
+                BTW Inhibit editsection links if requested in the page\r
+                IZ isset( $this->mDoubleUnderscores['noeditsection'] )  || $this->mOptions->getIsPrintable()\r
+                        I HAS showEditLink IZ 0\r
+                KTHX\r
+\r
+                BTW Get all headlines for numbering them and adding funky stuff like [edit]\r
+                BTW links - this is for later, but we need the number of headlines right now\r
+                I HAS matches IZ EMPTY\r
+                I HAS numMatches IZ preg_match_all( '/<H(?P<level>[1-6])(?P<attrib>.*?'.'>)(?P<header>.*?)<\/H[1-6] *>/i', $text, $matches )\r
+\r
+                BTW if there are fewer than 4 headlines in the article, do not show TOC\r
+                BTW unless it's been explicitly enabled.\r
+                enoughToc IZ $this->mShowToc &&\r
+                       ( ( $numMatches >= 4 ) || $this->mForceTocPosition );\r
+\r
+                BTW Allow user to stipulate that a page should have a "new section"\r
+                BTW link added via __NEWSECTIONLINK__\r
+                IZ isset( $this->mDoubleUnderscores['newsectionlink'] )\r
+                        IM ON UR SPECIAL mOutput->setNewSection DOING true\r
+                KTHX\r
+\r
+                BTW Allow user to remove the "new section"\r
+                BTW link via __NONEWSECTIONLINK__\r
+                IZ isset( $this->mDoubleUnderscores['nonewsectionlink'] )\r
+                        IM ON UR SPECIAL mOutput->hideNewSection DOING true\r
+                KTHX\r
+\r
+                BTW if the string __FORCETOC__ (not case-sensitive) occurs in the HTML,\r
+                BTW override above conditions and always show TOC above first header\r
+                IZ isset( $this->mDoubleUnderscores['forcetoc'] )\r
+                        UR SPECIAL mShowToc IZ true;\r
+                        I HAS enoughToc IZ true\r
+                KTHX\r
+\r
+                BTW We need this to perform operations on the HTML\r
+                I HAS sk IZ $this->mOptions->getSkin()\r
+\r
+                BTW headline counter\r
+                I HAS headlineCount IZ 0\r
+                I HAS numVisible IZ 0\r
+\r
+                BTW Ugh .. the TOC should have neat indentation levels which can be\r
+                BTW passed to the skin functions. These are determined here\r
+                I HAS toc IZ ''\r
+                I HAS full IZ ''\r
+                I HAS head IZ EMPTY\r
+                I HAS sublevelCount IZ EMPTY\r
+                I HAS levelCount IZ EMPTY\r
+                I HAS toclevel IZ 0\r
+                I HAS level IZ 0\r
+                I HAS prevlevel IZ 0\r
+                I HAS toclevel IZ 0\r
+                I HAS prevtoclevel IZ 0\r
+                I HAS markerRegex IZ "{$this->mUniqPrefix}-h-(\d+)-" . self::MARKER_SUFFIX\r
+                I HAS baseTitleText IZ $this->mTitle->getPrefixedDBkey()\r
+                I HAS oldType IZ $this->mOutputType\r
+                IM ON UR SPECIAL setOutputType DOING self::OT_WIKI\r
+                I HAS frame IZ $this->getPreprocessor()->newFrame()\r
+                I HAS root IZ $this->preprocessToDom( $origText )\r
+                I HAS node IZ $root->getFirstChild()\r
+                I HAS byteOffset IZ 0\r
+                I HAS tocraw IZ EMPTY\r
+\r
+               foreach ( $matches[3] as $headline ) {\r
+                        I HAS isTemplate IZ false\r
+                        I HAS titleText IZ false\r
+                        I HAS sectionIndex IZ false\r
+                        I HAS numbering IZ ''\r
+                        I HAS markerMatches IZ EMPTY\r
+                        IZ preg_match("/^$markerRegex/", $headline, $markerMatches )\r
+                                I HAS serial IZ $markerMatches[1]\r
+                               list( $titleText, $sectionIndex ) = $this->mHeadings[$serial];\r
+                                I HAS isTemplate IZ ( $titleText != $baseTitleText )\r
+                                I HAS headline IZ preg_replace( "/^$markerRegex/", "", $headline )\r
+                        KTHX\r
+\r
+                        IZ $toclevel\r
+                                I HAS prevlevel IZ $level\r
+                                I HAS prevtoclevel IZ $toclevel\r
+                        KTHX\r
+                        I HAS level IZ $matches[1][$headlineCount]\r
+\r
+                        IZ $level > $prevlevel\r
+                                BTW Increase TOC level\r
+                               $toclevel++;\r
+                               $sublevelCount[$toclevel] = 0;\r
+                                IZ $toclevel<$wgMaxTocLevel\r
+                                        I HAS prevtoclevel IZ $toclevel\r
+                                        toc HAS MOAR $sk->tocIndent();\r
+                                       $numVisible++;\r
+                                KTHX\r
+                        ORLY $level < $prevlevel && $toclevel > 1\r
+                                BTW Decrease TOC level, find level to jump to\r
+\r
+                               for ( $i = $toclevel; $i > 0; $i-- ) {\r
+                                        IZ $levelCount[$i] == $level\r
+                                                BTW Found last matching level\r
+                                                I HAS toclevel IZ $i\r
+                                               break;\r
+                                        ORLY $levelCount[$i] < $level\r
+                                                BTW Found first matching level below current level\r
+                                                I HAS toclevel IZ $i + 1\r
+                                               break;\r
+                                        KTHX\r
+                                KTHX\r
+                                IZ $i == 0\r
+                                        I HAS toclevel IZ 1\r
+                                KTHX\r
+                                IZ $toclevel<$wgMaxTocLevel\r
+                                        IZ $prevtoclevel < $wgMaxTocLevel\r
+                                                BTW Unindent only if the previous toc level was shown :p\r
+                                                toc HAS MOAR $sk->tocUnindent( $prevtoclevel - $toclevel );\r
+                                                I HAS prevtoclevel IZ $toclevel\r
+                                        NOWAI\r
+                                                toc HAS MOAR $sk->tocLineEnd();\r
+                                        KTHX\r
+                                KTHX\r
+                        NOWAI\r
+                                BTW No change in level, end TOC line\r
+                                IZ $toclevel<$wgMaxTocLevel\r
+                                        toc HAS MOAR $sk->tocLineEnd();\r
+                                KTHX\r
+                        KTHX\r
+\r
+                       $levelCount[$toclevel] = $level;\r
+\r
+                        BTW count number of headlines for each level\r
+                       @$sublevelCount[$toclevel]++;\r
+                        I HAS dot IZ 0\r
+                       for( $i = 1; $i <= $toclevel; $i++ ) {\r
+                                IZ !empty( $sublevelCount[$i] )\r
+                                        IZ $dot\r
+                                                numbering HAS MOAR '.';\r
+                                        KTHX\r
+                                        numbering HAS MOAR $wgContLang->formatNum( $sublevelCount[$i] );\r
+                                        I HAS dot IZ 1\r
+                                KTHX\r
+                        KTHX\r
+\r
+                        BTW The safe header is a version of the header text safe to use for links\r
+                        BTW Avoid insertion of weird stuff like <math> by expanding the relevant sections\r
+                        I HAS safeHeadline IZ $this->mStripState->unstripBoth( $headline )\r
+\r
+                        BTW Remove link placeholders by the link text.\r
+                        BTW     <!--LINK number-->\r
+                        BTW turns into\r
+                        BTW     link text with suffix\r
+                        I HAS safeHeadline IZ $this->replaceLinkHoldersText( $safeHeadline )\r
+\r
+                        BTW Strip out HTML (other than plain <sup> and <sub>: bug 8393)\r
+                        tocline IZ preg_replace(\r
+                               array( '#<(?!/?(sup|sub)).*?'.'>#', '#<(/?(sup|sub)).*?'.'>#' ),\r
+                               array( '',                          '<$1>' ),\r
+                               $safeHeadline\r
+                        BUCKET\r
+                        I HAS tocline IZ trim( $tocline )\r
+\r
+                        BTW For the anchor, strip out HTML-y stuff period\r
+                        I HAS safeHeadline IZ preg_replace( '/<.*?'.'>/', '', $safeHeadline )\r
+                        I HAS safeHeadline IZ preg_replace( '/[ _]+/', ' ', $safeHeadline )\r
+                        I HAS safeHeadline IZ trim( $safeHeadline )\r
+\r
+                        BTW Save headline for section edit hint before it's escaped\r
+                        I HAS headlineHint IZ $safeHeadline\r
+\r
+                        IZ $wgHtml5 && $wgExperimentalHtmlIds\r
+                                BTW For reverse compatibility, provide an id that's\r
+                                BTW HTML4-compatible, like we used to.\r
+                                BTW \r
+                                BTW It may be worth noting, academically, that it's possible for\r
+                                BTW the legacy anchor to conflict with a non-legacy headline\r
+                                BTW anchor on the page.  In this case likely the "correct" thing\r
+                                BTW would be to either drop the legacy anchors or make sure\r
+                                BTW they're numbered first.  However, this would require people\r
+                                BTW to type in section names like "abc_.D7.93.D7.90.D7.A4"\r
+                                BTW manually, so let's not bother worrying about it.\r
+                                legacyHeadline IZ Sanitizer::escapeId( $safeHeadline,\r
+                                        IM ON UR array DOING 'noninitial', 'legacy' )\r
+                                I HAS safeHeadline IZ Sanitizer::escapeId( $safeHeadline )\r
+\r
+                                IZ $legacyHeadline == $safeHeadline\r
+                                        BTW No reason to have both (in fact, we can't)\r
+                                        I HAS legacyHeadline IZ false\r
+                                KTHX\r
+                        NOWAI\r
+                                I HAS legacyHeadline IZ false\r
+                                safeHeadline IZ Sanitizer::escapeId( $safeHeadline,\r
+                                       'noninitial' );\r
+                        KTHX\r
+\r
+                        BTW HTML names must be case-insensitively unique (bug 10721).  FIXME:\r
+                        BTW Does this apply to Unicode characters?  Because we aren't\r
+                        BTW handling those here.\r
+                        I HAS arrayKey IZ strtolower( $safeHeadline )\r
+                        IZ $legacyHeadline === false\r
+                                I HAS legacyArrayKey IZ false\r
+                        NOWAI\r
+                                I HAS legacyArrayKey IZ strtolower( $legacyHeadline )\r
+                        KTHX\r
+\r
+                        BTW count how many in assoc. array so we can track dupes in anchors\r
+                        IZ isset( $refers[$arrayKey] )\r
+                               $refers[$arrayKey]++;\r
+                        NOWAI\r
+                               $refers[$arrayKey] = 1;\r
+                        KTHX\r
+                        IZ isset( $refers[$legacyArrayKey] )\r
+                               $refers[$legacyArrayKey]++;\r
+                        NOWAI\r
+                               $refers[$legacyArrayKey] = 1;\r
+                        KTHX\r
+\r
+                        BTW Don't number the heading if it is the only one (looks silly)\r
+                       if ( $doNumberHeadings && count( $matches[3] ) > 1) {\r
+                                BTW the two are different if the line contains a link\r
+                                I HAS headline IZ $numbering . ' ' . $headline\r
+                        KTHX\r
+\r
+                        BTW Create the anchor for linking from the TOC to the section\r
+                        I HAS anchor IZ $safeHeadline\r
+                        I HAS legacyAnchor IZ $legacyHeadline\r
+                        IZ $refers[$arrayKey] > 1\r
+                                anchor HAS MOAR '_' . $refers[$arrayKey];\r
+                        KTHX\r
+                        IZ $legacyHeadline !== false && $refers[$legacyArrayKey] > 1\r
+                                legacyAnchor HAS MOAR '_' . $refers[$legacyArrayKey];\r
+                        KTHX\r
+                        IZ $enoughToc && ( !isset( $wgMaxTocLevel ) || $toclevel < $wgMaxTocLevel )\r
+                                toc HAS MOAR $sk->tocLine( $anchor, $tocline,\r
+                                       $numbering, $toclevel, ( $isTemplate ? false : $sectionIndex ) );\r
+                        KTHX\r
+\r
+                        BTW Add the section to the section tree\r
+                        BTW Find the DOM node for this header\r
+                        STEALIN UR $node && !$isTemplate\r
+                                IZ $node->getName() === 'h'\r
+                                        I HAS bits IZ $node->splitHeading()\r
+                                       if ( $bits['i'] == $sectionIndex )\r
+                                               break;\r
+                                KTHX\r
+                               $byteOffset += mb_strlen( $this->mStripState->unstripBoth(\r
+                                       $frame->expand( $node, PPFrame::RECOVER_ORIG ) ) );\r
+                                I HAS node IZ $node->getNextSibling()\r
+                        KTHX\r
+                       $tocraw[] = array(\r
+                               'toclevel' => $toclevel,\r
+                               'level' => $level,\r
+                               'line' => $tocline,\r
+                               'number' => $numbering,\r
+                               'index' => ( $isTemplate ? 'T-' : '' ) . $sectionIndex,\r
+                               'fromtitle' => $titleText,\r
+                               'byteoffset' => ( $isTemplate ? null : $byteOffset ),\r
+                               'anchor' => $anchor,\r
+                        BUCKET\r
+\r
+                        BTW give headline the correct <h#> tag\r
+                        IZ $showEditLink && $sectionIndex !== false\r
+                                IZ $isTemplate\r
+                                        BTW Put a T flag in the section identifier, to indicate to extractSections()\r
+                                        BTW that sections inside <includeonly> should be counted.\r
+                                        I HAS editlink IZ $sk->doEditSectionLink( Title::newFromText( $titleText ), "T-$sectionIndex" )\r
+                                NOWAI\r
+                                        I HAS editlink IZ $sk->doEditSectionLink( $this->mTitle, $sectionIndex, $headlineHint )\r
+                                KTHX\r
+                        NOWAI\r
+                                I HAS editlink IZ ''\r
+                        KTHX\r
+                       $head[$headlineCount] = $sk->makeHeadline( $level,\r
+                               $matches['attrib'][$headlineCount], $anchor, $headline,\r
+                               $editlink, $legacyAnchor );\r
+\r
+                       $headlineCount++;\r
+                KTHX\r
+\r
+                IM ON UR SPECIAL setOutputType DOING $oldType\r
+\r
+                BTW Never ever show TOC if no headers\r
+                IZ $numVisible < 1\r
+                        I HAS enoughToc IZ false\r
+                KTHX\r
+\r
+                IZ $enoughToc\r
+                        IZ $prevtoclevel > 0 && $prevtoclevel < $wgMaxTocLevel\r
+                                toc HAS MOAR $sk->tocUnindent( $prevtoclevel - 1 );\r
+                        KTHX\r
+                        I HAS toc IZ $sk->tocList( $toc )\r
+                        IM ON UR SPECIAL mOutput->setTOCHTML DOING $toc\r
+                KTHX\r
+\r
+                IZ $isMain\r
+                        IM ON UR SPECIAL mOutput->setSections DOING $tocraw\r
+                KTHX\r
+\r
+                BTW split up and insert constructed headlines\r
+\r
+                I HAS blocks IZ preg_split( '/<H[1-6].*?' . '>.*?<\/H[1-6]>/i', $text )\r
+                I HAS i IZ 0\r
+\r
+                IM IN UR blocks ITZA block\r
+                        IZ $showEditLink && $headlineCount > 0 && $i == 0 && $block !== "\n"\r
+                                BTW This is the [edit] link that appears for the top block of text when\r
+                                BTW section editing is enabled\r
+\r
+                                BTW Disabled because it broke block formatting\r
+                                BTW For example, a bullet point in the top line\r
+                                BTW $full .= $sk->editSectionLink(0);\r
+                        KTHX\r
+                        full HAS MOAR $block;\r
+                        IZ $enoughToc && !$i && $isMain && !$this->mForceTocPosition\r
+                                BTW Top anchor now in skin\r
+                                I HAS full IZ $full.$toc\r
+                        KTHX\r
+\r
+                        IZ !empty( $head[$i] )\r
+                                full HAS MOAR $head[$i];\r
+                        KTHX\r
+                       $i++;\r
+                KTHX\r
+                IZ $this->mForceTocPosition\r
+                        I FOUND MAH str_replace( '<!--MWTOC-->', $toc, $full )\r
+                NOWAI\r
+                        I FOUND MAH $full\r
+                KTHX\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Merge $tree2 into $tree1 by replacing the section with index\r
+         NOT WANT $section in $tree1 and its descendants with the sections in $tree2.\r
+         NOT WANT Note that in the returned section tree, only the 'index' and\r
+         NOT WANT 'byteoffset' fields are guaranteed to be correct.\r
+         NOT WANT @param $tree1 array Section tree from ParserOutput::getSectons()\r
+        NOT WANT  @param $tree2 array Section tree\r
+         NOT WANT @param $section int Section index\r
+         NOT WANT @param $title Title Title both section trees come from\r
+         NOT WANT @param $len2 int Length of the original wikitext for $tree2\r
+         NOT WANT @return array Merged section tree\r
+         WANT\r
+        SO IM ALWAYS LIKE mergeSectionTrees WITH UR $tree1, $tree2, $section, $title, $len2\r
+                I HAS UR $wgContLang ON UR INTERNETS\r
+                I HAS newTree IZ EMPTY\r
+                I HAS targetLevel IZ false\r
+                I HAS merged IZ false\r
+                I HAS lastLevel IZ 1\r
+                I HAS nextIndex IZ 1\r
+                I HAS numbering IZ BUCKET 0 );\r
+                I HAS titletext IZ $title->getPrefixedDBkey()\r
+                IM IN UR tree1 ITZA s\r
+                        IZ $targetLevel !== false\r
+                                IZ $s['level'] <= $targetLevel\r
+                                        BTW We've skipped enough\r
+                                        I HAS targetLevel IZ false\r
+                                NOWAI\r
+                                       continue;\r
+                                KTHX\r
+                        KTHX\r
+                       if ( $s['index'] != $section ||\r
+                                       $s['fromtitle'] != $titletext ) {\r
+                               self::incrementNumbering( $numbering,\r
+                                       $s['toclevel'], $lastLevel );\r
+\r
+                                BTW Rewrite index, byteoffset and number\r
+                                IZ $s['fromtitle'] == $titletext\r
+                                       $s['index'] = $nextIndex++;\r
+                                        IZ $merged\r
+                                               $s['byteoffset'] += $len2;\r
+                                        KTHX\r
+                                KTHX\r
+                               $s['number']  = implode( '.', array_map(\r
+                                       array( $wgContLang, 'formatnum' ),\r
+                                       $numbering ) );\r
+                                I HAS lastLevel IZ $s['toclevel']\r
+                               $newTree[] = $s;\r
+                        NOWAI\r
+                                BTW We're at $section\r
+                                BTW Insert sections from $tree2 here\r
+                                IM IN UR tree2 ITZA s2\r
+                                        BTW Rewrite the fields in $s2\r
+                                        BTW before inserting it\r
+                                       $s2['toclevel'] += $s['toclevel'] - 1;\r
+                                       $s2['level'] += $s['level'] - 1;\r
+                                       $s2['index'] = $nextIndex++;\r
+                                       $s2['byteoffset'] += $s['byteoffset'];\r
+\r
+                                       self::incrementNumbering( $numbering,\r
+                                               $s2['toclevel'], $lastLevel );\r
+                                       $s2['number']  = implode( '.', array_map(\r
+                                               array( $wgContLang, 'formatnum' ),\r
+                                               $numbering ) );\r
+                                        I HAS lastLevel IZ $s2['toclevel']\r
+                                       $newTree[] = $s2;\r
+                                KTHX\r
+                                BTW Skip all descendants of $section in $tree1\r
+                                I HAS targetLevel IZ $s['level']\r
+                                I HAS merged IZ true\r
+                        KTHX\r
+                KTHX\r
+                I FOUND MAH $newTree\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Increment a section number. Helper function for mergeSectionTrees()\r
+         NOT WANT @param $number array Array representing a section number\r
+         NOT WANT @param $level int Current TOC level (depth)\r
+         NOT WANT @param $lastLevel int Level of previous TOC entry\r
+         WANT\r
+        SO IM ALWAYS LIKE incrementNumbering WITH UR &$number, $level, $lastLevel\r
+                IZ $level > $lastLevel\r
+                       $number[$level - 1] = 1;\r
+                ORLY $level < $lastLevel\r
+                       foreach ( $number as $key => $unused )\r
+                                IZ $key >= $level\r
+                                        IM ON UR unset DOING $number[$key]\r
+                                KTHX\r
+                       $number[$level - 1]++;\r
+                NOWAI\r
+                       $number[$level - 1]++;\r
+                KTHX\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Transform wiki markup when saving a page by doing \r\n -> \n\r
+         NOT WANT conversion, substitting signatures, {{subst:}} templates, etc.\r
+         NOT WANT \r
+         NOT WANT @param string $text the text to transform\r
+         NOT WANT @param Title &$title the Title object for the current article\r
+         NOT WANT @param User $user the User object describing the current user\r
+         NOT WANT @param ParserOptions $options parsing options\r
+         NOT WANT @param bool $clearState whether to clear the parser state first\r
+         NOT WANT @return string the altered wiki markup\r
+         NOT WANT @public\r
+         WANT\r
+        SO IM LIKE preSaveTransform WITH UR $text, Title $title, $user, $options, $clearState = true\r
+                UR SPECIAL mOptions IZ $options;\r
+                IM ON UR SPECIAL setTitle DOING $title\r
+                IM ON UR SPECIAL setOutputType DOING self::OT_WIKI\r
+\r
+                IZ $clearState\r
+                        IM ON UR SPECIAL clearState\r
+                KTHX\r
+\r
+                I HAS pairs IZ BUCKET\r
+                       "\r\n" => "\n",\r
+                BUCKET\r
+                I HAS text IZ str_replace( array_keys( $pairs ), array_values( $pairs ), $text )\r
+                I HAS text IZ $this->pstPass2( $text, $user )\r
+                I HAS text IZ $this->mStripState->unstripBoth( $text )\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Pre-save transform helper function\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE pstPass2 WITH UR $text, $user\r
+                I HAS UR $wgContLang, $wgLocaltimezone ON UR INTERNETS\r
+\r
+                BTW Note: This is the timestamp saved as hardcoded wikitext to\r
+                BTW the database, we use $wgContLang here in order to give\r
+                BTW everyone the same signature and use the default one rather\r
+                BTW than the one selected in each user's preferences.\r
+                BTW (see also bug 12815)\r
+                I HAS ts IZ $this->mOptions->getTimestamp()\r
+                IZ isset( $wgLocaltimezone )\r
+                        I HAS tz IZ $wgLocaltimezone\r
+                NOWAI\r
+                        I HAS tz IZ date_default_timezone_get()\r
+                KTHX\r
+\r
+                I HAS unixts IZ wfTimestamp( TS_UNIX, $ts )\r
+                I HAS oldtz IZ date_default_timezone_get()\r
+                IM ON UR date_default_timezone_set DOING $tz\r
+                I HAS ts IZ date( 'YmdHis', $unixts )\r
+                I HAS tzMsg IZ date( 'T', $unixts )  # might vary on DST changeover!\r
+\r
+                BTW Allow translation of timezones trough wiki. date() can return\r
+                BTW whatever crap the system uses, localised or not, so we cannot\r
+                BTW ship premade translations.\r
+                I HAS key IZ 'timezone-' . strtolower( trim( $tzMsg ) )\r
+                I HAS value IZ wfMsgForContent( $key )\r
+                IZ !wfEmptyMsg( $key, $value )\r
+                        I HAS tzMsg IZ $value\r
+                KTHX\r
+\r
+                IM ON UR date_default_timezone_set DOING $oldtz\r
+\r
+                I HAS d IZ $wgContLang->timeanddate( $ts, false, false ) . " ($tzMsg)"\r
+\r
+                BTW Variable replacement\r
+                BTW Because mOutputType is OT_WIKI, this will only process {{subst:xxx}} type tags\r
+                I HAS text IZ $this->replaceVariables( $text )\r
+\r
+                BTW Signatures\r
+                I HAS sigText IZ $this->getUserSig( $user )\r
+                text IZ strtr( $text, array(\r
+                       '~~~~~' => $d,\r
+                       '~~~~' => "$sigText $d",\r
+                       '~~~' => $sigText\r
+               ) );\r
+\r
+                BTW Context links: [[|name]] and [[name (context)|]]\r
+                I HAS UR $wgLegalTitleChars ON UR INTERNETS\r
+                I HAS tc IZ "[$wgLegalTitleChars]"\r
+                I HAS nc IZ '[ _0-9A-Za-z\x80-\xff-]' # Namespaces can use non-ascii!\r
+\r
+                I HAS p1 IZ "/\[\[(:?$nc+:|:|)($tc+?)( \\($tc+\\))\\|]]/"              # [[ns:page (context)|]]\r
+                I HAS p4 IZ "/\[\[(:?$nc+:|:|)($tc+?)(($tc+))\\|]]/"               # [[ns:page(context)|]]\r
+                I HAS p3 IZ "/\[\[(:?$nc+:|:|)($tc+?)( \\($tc+\\)|)(, $tc+|)\\|]]/"    # [[ns:page (context), context|]]\r
+                I HAS p2 IZ "/\[\[\\|($tc+)]]/"                                        # [[|page]]\r
+\r
+                BTW try $p1 first, to turn "[[A, B (C)|]]" into "[[A, B (C)|A, B]]"\r
+                I HAS text IZ preg_replace( $p1, '[[\\1\\2\\3|\\2]]', $text )\r
+                I HAS text IZ preg_replace( $p4, '[[\\1\\2\\3|\\2]]', $text )\r
+                I HAS text IZ preg_replace( $p3, '[[\\1\\2\\3\\4|\\2]]', $text )\r
+\r
+                I HAS t IZ $this->mTitle->getText()\r
+                I HAS m IZ EMPTY\r
+                IZ preg_match( "/^($nc+:|)$tc+?( \\($tc+\\))$/", $t, $m )\r
+                        I HAS text IZ preg_replace( $p2, "[[$m[1]\\1$m[2]|\\1]]", $text )\r
+                ORLY preg_match( "/^($nc+:|)$tc+?(, $tc+|)$/", $t, $m ) && "$m[1]$m[2]" != ''\r
+                        I HAS text IZ preg_replace( $p2, "[[$m[1]\\1$m[2]|\\1]]", $text )\r
+                NOWAI\r
+                        BTW if there's no context, don't bother duplicating the title\r
+                        I HAS text IZ preg_replace( $p2, '[[\\1]]', $text )\r
+                KTHX\r
+\r
+                BTW Trim trailing whitespace\r
+                I HAS text IZ rtrim( $text )\r
+\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Fetch the user's signature text, if any, and normalize to\r
+         NOT WANT validated, ready-to-insert wikitext.\r
+         NOT WANT If you have pre-fetched the nickname or the fancySig option, you can\r
+         NOT WANT specify them here to save a database query.\r
+         NOT WANT \r
+         NOT WANT @param User $user\r
+         NOT WANT @return string\r
+         WANT\r
+        SO IM LIKE getUserSig WITH UR &$user, $nickname = false, $fancySig = null\r
+                I HAS UR $wgMaxSigChars ON UR INTERNETS\r
+\r
+                I HAS username IZ $user->getName()\r
+\r
+                BTW If not given, retrieve from the user object.\r
+               if ( $nickname === false )\r
+                        I HAS nickname IZ $user->getOption( 'nickname' )\r
+\r
+                IZ is_null( $fancySig )\r
+                        I HAS fancySig IZ $user->getBoolOption( 'fancysig' )\r
+                KTHX\r
+\r
+                I HAS nickname IZ $nickname == null ? $username : $nickname\r
+\r
+                IZ mb_strlen( $nickname ) > $wgMaxSigChars\r
+                        I HAS nickname IZ $username\r
+                        IM ON UR wfDebug DOING __METHOD__ . ": $username has overlong signature.\n"\r
+                ORLY $fancySig !== false\r
+                        BTW Sig. might contain markup; validate this\r
+                        IZ $this->validateSig( $nickname ) !== false\r
+                                BTW Validated; clean up (if needed) and return it\r
+                                I FOUND MAH $this->cleanSig( $nickname, true )\r
+                        NOWAI\r
+                                BTW Failed to validate; fall back to the default\r
+                                I HAS nickname IZ $username\r
+                                IM ON UR wfDebug DOING __METHOD__.": $username has bad XML tags in signature.\n"\r
+                        KTHX\r
+                KTHX\r
+\r
+                BTW Make sure nickname doesnt get a sig in a sig\r
+                I HAS nickname IZ $this->cleanSigInSig( $nickname )\r
+\r
+                BTW If we're still here, make it a link to the user page\r
+                I HAS userText IZ wfEscapeWikiText( $username )\r
+                I HAS nickText IZ wfEscapeWikiText( $nickname )\r
+               if ( $user->isAnon() )  {\r
+                        I FOUND MAH wfMsgExt( 'signature-anon', array( 'content', 'parsemag' ), $userText, $nickText )\r
+                NOWAI\r
+                        I FOUND MAH wfMsgExt( 'signature', array( 'content', 'parsemag' ), $userText, $nickText )\r
+                KTHX\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Check that the user's signature contains no bad XML\r
+         NOT WANT \r
+         NOT WANT @param string $text\r
+         NOT WANT @return mixed An expanded string, or false if invalid.\r
+         WANT\r
+        SO IM LIKE validateSig WITH UR $text\r
+                IM ON UR return DOING Xml::isWellFormedXmlFragment( $text ) ? $text : false\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Clean up signature text\r
+         NOT WANT \r
+         NOT WANT 1) Strip ~~~, ~~~~ and ~~~~~ out of signatures @see cleanSigInSig\r
+         NOT WANT 2) Substitute all transclusions\r
+         NOT WANT \r
+         NOT WANT @param string $text\r
+         NOT WANT @param $parsing Whether we're cleaning (preferences save) or parsing\r
+         NOT WANT @return string Signature text\r
+         WANT\r
+        SO IM LIKE cleanSig WITH UR $text, $parsing = false\r
+                IZ !$parsing\r
+                        I HAS UR $wgTitle ON UR INTERNETS\r
+                        IM ON UR SPECIAL clearState\r
+                        IM ON UR SPECIAL setTitle DOING $wgTitle\r
+                        UR SPECIAL mOptions IZ new ParserOptions;\r
+                        UR SPECIAL setOutputType IZ self::OT_PREPROCESS;\r
+                KTHX\r
+\r
+                BTW Option to disable this feature\r
+                IZ !$this->mOptions->getCleanSignatures()\r
+                        I FOUND MAH $text\r
+                KTHX\r
+\r
+                BTW FIXME: regex doesn't respect extension tags or nowiki\r
+                BTW  => Move this logic to braceSubstitution()\r
+                I HAS substWord IZ MagicWord::get( 'subst' )\r
+                I HAS substRegex IZ '/\{\{(?!(?:' . $substWord->getBaseRegex() . '))/x' . $substWord->getRegexCase()\r
+                I HAS substText IZ '{{' . $substWord->getSynonym( 0 )\r
+\r
+                I HAS text IZ preg_replace( $substRegex, $substText, $text )\r
+                I HAS text IZ $this->cleanSigInSig( $text )\r
+                I HAS dom IZ $this->preprocessToDom( $text )\r
+                I HAS frame IZ $this->getPreprocessor()->newFrame()\r
+                I HAS text IZ $frame->expand( $dom )\r
+\r
+                IZ !$parsing\r
+                        I HAS text IZ $this->mStripState->unstripBoth( $text )\r
+                KTHX\r
+\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Strip ~~~, ~~~~ and ~~~~~ out of signatures\r
+         NOT WANT @param string $text\r
+         NOT WANT @return string Signature text with /~{3,5}/ removed\r
+         WANT\r
+        SO IM LIKE cleanSigInSig WITH UR $text\r
+                I HAS text IZ preg_replace( '/~{3,5}/', '', $text )\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Set up some variables which are usually set up in parse()\r
+         NOT WANT so that an external function can call some class members with confidence\r
+         NOT WANT @public\r
+         WANT\r
+        SO IM LIKE startExternalParse WITH UR &$title, $options, $outputType, $clearState = true\r
+                IM ON UR SPECIAL setTitle DOING $title\r
+                UR SPECIAL mOptions IZ $options;\r
+                IM ON UR SPECIAL setOutputType DOING $outputType\r
+                IZ $clearState\r
+                        IM ON UR SPECIAL clearState\r
+                KTHX\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Wrapper for preprocess()\r
+         NOT WANT \r
+         NOT WANT @param string $text the text to preprocess\r
+         NOT WANT @param ParserOptions $options  options\r
+         NOT WANT @return string\r
+         NOT WANT @public\r
+         WANT\r
+        SO IM LIKE transformMsg WITH UR $text, $options\r
+                I HAS UR $wgTitle ON UR INTERNETS\r
+               static $executing = false;\r
+\r
+                BTW Guard against infinite recursion\r
+                IZ $executing\r
+                        I FOUND MAH $text\r
+                KTHX\r
+                I HAS executing IZ true\r
+\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+                I HAS text IZ $this->preprocess( $text, $wgTitle, $options )\r
+\r
+                I HAS executing IZ false\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Create an HTML-style tag, e.g. <yourtag>special text</yourtag>\r
+         NOT WANT The callback should have the following form:\r
+         NOT WANT    function myParserHook( $text, $params, &$parser ) { ... }\r
+         NOT WANT \r
+         NOT WANT Transform and return $text. Use $parser for any required context, e.g. use\r
+         NOT WANT $parser->getTitle() and $parser->getOptions() not $wgTitle or $wgOut->mParserOptions\r
+         NOT WANT \r
+         NOT WANT @public\r
+         NOT WANT \r
+         NOT WANT @param mixed $tag The tag to use, e.g. 'hook' for <hook>\r
+         NOT WANT @param mixed $callback The callback function (and object) to use for the tag\r
+         NOT WANT \r
+         NOT WANT @return The old value of the mTagHooks array associated with the hook\r
+         WANT\r
+        SO IM LIKE setHook WITH UR $tag, $callback\r
+                I HAS tag IZ strtolower( $tag )\r
+                I HAS oldVal IZ isset( $this->mTagHooks[$tag] ) ? $this->mTagHooks[$tag] : null\r
+               $this->mTagHooks[$tag] = $callback;\r
+                IZ !in_array( $tag, $this->mStripList )\r
+                       $this->mStripList[] = $tag;\r
+                KTHX\r
+\r
+                I FOUND MAH $oldVal\r
+        KTHX\r
+\r
+        SO IM LIKE setTransparentTagHook WITH UR $tag, $callback\r
+                I HAS tag IZ strtolower( $tag )\r
+                I HAS oldVal IZ isset( $this->mTransparentTagHooks[$tag] ) ? $this->mTransparentTagHooks[$tag] : null\r
+               $this->mTransparentTagHooks[$tag] = $callback;\r
+\r
+                I FOUND MAH $oldVal\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Remove all tag hooks\r
+         WANT\r
+        SO IM LIKE clearTagHooks\r
+                UR SPECIAL mTagHooks IZ EMPTY;\r
+                UR SPECIAL mStripList IZ $this->mDefaultStripList;\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Create a function, e.g. {{sum:1|2|3}}\r
+         NOT WANT The callback function should have the form:\r
+         NOT WANT    function myParserFunction( &$parser, $arg1, $arg2, $arg3 ) { ... }\r
+         NOT WANT \r
+         NOT WANT Or with SFH_OBJECT_ARGS:\r
+         NOT WANT    function myParserFunction( $parser, $frame, $args ) { ... }\r
+         NOT WANT \r
+         NOT WANT The callback may either return the text result of the function, or an array with the text\r
+         NOT WANT in element 0, and a number of flags in the other elements. The names of the flags are\r
+         NOT WANT specified in the keys. Valid flags are:\r
+         NOT WANT   found                     The text returned is valid, stop processing the template. This\r
+         NOT WANT                             is on by default.\r
+         NOT WANT   nowiki                    Wiki markup in the return value should be escaped\r
+         NOT WANT   isHTML                    The returned text is HTML, armour it against wikitext transformation\r
+         NOT WANT \r
+         NOT WANT @public\r
+         NOT WANT \r
+         NOT WANT @param string $id The magic word ID\r
+         NOT WANT @param mixed $callback The callback function (and object) to use\r
+         NOT WANT @param integer $flags a combination of the following flags:\r
+         NOT WANT     SFH_NO_HASH   No leading hash, i.e. {{plural:...}} instead of {{#if:...}}\r
+         NOT WANT \r
+         NOT WANT     SFH_OBJECT_ARGS   Pass the template arguments as PPNode objects instead of text. This\r
+         NOT WANT     allows for conditional expansion of the parse tree, allowing you to eliminate dead\r
+         NOT WANT     branches and thus speed up parsing. It is also possible to analyse the parse tree of\r
+         NOT WANT     the arguments, and to control the way they are expanded.\r
+         NOT WANT \r
+         NOT WANT     The $frame parameter is a PPFrame. This can be used to produce expanded text from the\r
+         NOT WANT     arguments, for instance:\r
+         NOT WANT         $text = isset( $args[0] ) ? $frame->expand( $args[0] ) : '';\r
+         NOT WANT \r
+         NOT WANT     For technical reasons, $args[0] is pre-expanded and will be a string. This may change in\r
+         NOT WANT     future versions. Please call $frame->expand() on it anyway so that your code keeps\r
+         NOT WANT     working if/when this is changed.\r
+         NOT WANT \r
+         NOT WANT     If you want whitespace to be trimmed from $args, you need to do it yourself, post-\r
+         NOT WANT     expansion.\r
+         NOT WANT \r
+         NOT WANT     Please read the documentation in includes/parser/Preprocessor.php for more information\r
+         NOT WANT     about the methods available in PPFrame and PPNode.\r
+         NOT WANT \r
+         NOT WANT @return The old callback function for this name, if any\r
+         WANT\r
+        SO IM LIKE setFunctionHook WITH UR $id, $callback, $flags = 0\r
+                I HAS UR $wgContLang ON UR INTERNETS\r
+\r
+                I HAS oldVal IZ isset( $this->mFunctionHooks[$id] ) ? $this->mFunctionHooks[$id][0] : null\r
+               $this->mFunctionHooks[$id] = array( $callback, $flags );\r
+\r
+                BTW Add to function cache\r
+                I HAS mw IZ MagicWord::get( $id )\r
+               if ( !$mw )\r
+                       throw new MWException( __METHOD__.'() expecting a magic word identifier.' );\r
+\r
+                I HAS synonyms IZ $mw->getSynonyms()\r
+                I HAS sensitive IZ intval( $mw->isCaseSensitive() )\r
+\r
+                IM IN UR synonyms ITZA syn\r
+                        BTW Case\r
+                        IZ !$sensitive\r
+                                I HAS syn IZ $wgContLang->lc( $syn )\r
+                        KTHX\r
+                        BTW Add leading hash\r
+                        IZ !( $flags & SFH_NO_HASH )\r
+                                I HAS syn IZ '#' . $syn\r
+                        KTHX\r
+                        BTW Remove trailing colon\r
+                        IZ substr( $syn, -1, 1 ) === ':'\r
+                                I HAS syn IZ substr( $syn, 0, -1 )\r
+                        KTHX\r
+                       $this->mFunctionSynonyms[$sensitive][$syn] = $id;\r
+                KTHX\r
+                I FOUND MAH $oldVal\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Get all registered function hook identifiers\r
+         NOT WANT \r
+         NOT WANT @return array\r
+         WANT\r
+        SO IM LIKE getFunctionHooks\r
+                I FOUND MAH array_keys( $this->mFunctionHooks )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Create a tag function, e.g. <test>some stuff</test>.\r
+         NOT WANT Unlike tag hooks, tag functions are parsed at preprocessor level.\r
+         NOT WANT Unlike parser functions, their content is not preprocessed.\r
+         WANT\r
+        SO IM LIKE setFunctionTagHook WITH UR $tag, $callback, $flags\r
+                I HAS tag IZ strtolower( $tag )\r
+                old IZ isset( $this->mFunctionTagHooks[$tag] ) ?\r
+                       $this->mFunctionTagHooks[$tag] : null;\r
+               $this->mFunctionTagHooks[$tag] = array( $callback, $flags );\r
+\r
+                IZ !in_array( $tag, $this->mStripList )\r
+                       $this->mStripList[] = $tag;\r
+                KTHX\r
+\r
+                I FOUND MAH $old\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT FIXME: update documentation. makeLinkObj() is deprecated.\r
+         NOT WANT Replace <!--LINK--> link placeholders with actual links, in the buffer\r
+         NOT WANT Placeholders created in Skin::makeLinkObj()\r
+         NOT WANT Returns an array of link CSS classes, indexed by PDBK.\r
+         WANT\r
+        SO IM LIKE replaceLinkHolders WITH UR &$text, $options = 0\r
+                I FOUND MAH $this->mLinkHolders->replace( $text )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Replace <!--LINK--> link placeholders with plain text of links\r
+         NOT WANT (not HTML-formatted).\r
+         NOT WANT @param string $text\r
+         NOT WANT @return string\r
+         WANT\r
+        SO IM LIKE replaceLinkHoldersText WITH UR $text\r
+                I FOUND MAH $this->mLinkHolders->replaceText( $text )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Renders an image gallery from a text with one line per image.\r
+         NOT WANT text labels may be given by using |-style alternative text. E.g.\r
+         NOT WANT   Image:one.jpg|The number "1"\r
+         NOT WANT   Image:tree.jpg|A tree\r
+         NOT WANT given as text will return the HTML of a gallery with two images,\r
+         NOT WANT labeled 'The number "1"' and\r
+         NOT WANT 'A tree'.\r
+         WANT\r
+        SO IM LIKE renderImageGallery WITH UR $text, $params\r
+                I HAS ig IZ new ImageGallery()\r
+               $ig->setContextTitle( $this->mTitle );\r
+               $ig->setShowBytes( false );\r
+               $ig->setShowFilename( false );\r
+               $ig->setParser( $this );\r
+               $ig->setHideBadImages();\r
+               $ig->setAttributes( Sanitizer::validateTagAttributes( $params, 'table' ) );\r
+               $ig->useSkin( $this->mOptions->getSkin() );\r
+               $ig->mRevisionId = $this->mRevisionId;\r
+\r
+                IZ isset( $params['showfilename'] )\r
+                       $ig->setShowFilename( true );\r
+                NOWAI\r
+                       $ig->setShowFilename( false );\r
+                KTHX\r
+                IZ isset( $params['caption'] )\r
+                        I HAS caption IZ $params['caption']\r
+                        I HAS caption IZ htmlspecialchars( $caption )\r
+                        I HAS caption IZ $this->replaceInternalLinks( $caption )\r
+                       $ig->setCaptionHtml( $caption );\r
+                KTHX\r
+                IZ isset( $params['perrow'] )\r
+                       $ig->setPerRow( $params['perrow'] );\r
+                KTHX\r
+                IZ isset( $params['widths'] )\r
+                       $ig->setWidths( $params['widths'] );\r
+                KTHX\r
+                IZ isset( $params['heights'] )\r
+                       $ig->setHeights( $params['heights'] );\r
+                KTHX\r
+\r
+                IM ON UR wfRunHooks DOING 'BeforeParserrenderImageGallery', array( &$this, &$ig )\r
+\r
+                I HAS lines IZ StringUtils::explode( "\n", $text )\r
+                IM IN UR lines ITZA line\r
+                        BTW match lines like these:\r
+                        BTW Image:someimage.jpg|This is some image\r
+                        I HAS matches IZ EMPTY\r
+                        IM ON UR preg_match DOING "/^([^|]+)(\\|(.*))?$/", $line, $matches\r
+                        BTW Skip empty lines\r
+                        IZ count( $matches ) == 0\r
+                               continue;\r
+                        KTHX\r
+\r
+                        IZ strpos( $matches[0], '%' ) !== false\r
+                               $matches[1] = urldecode( $matches[1] );\r
+                        KTHX\r
+                        I HAS tp IZ Title::newFromText( $matches[1] )\r
+                       $nt =& $tp;\r
+                        IZ is_null( $nt )\r
+                                BTW Bogus title. Ignore these so we don't bomb out later.\r
+                               continue;\r
+                        KTHX\r
+                        IZ isset( $matches[3] )\r
+                                I HAS label IZ $matches[3]\r
+                        NOWAI\r
+                                I HAS label IZ ''\r
+                        KTHX\r
+\r
+                        I HAS html IZ $this->recursiveTagParse( trim( $label ) )\r
+\r
+                       $ig->add( $nt, $html );\r
+\r
+                        BTW Only add real images (bug #5586)\r
+                        IZ $nt->getNamespace() == NS_FILE\r
+                                IM ON UR SPECIAL mOutput->addImage DOING $nt->getDBkey()\r
+                        KTHX\r
+                KTHX\r
+                I FOUND MAH $ig->toHTML()\r
+        KTHX\r
+\r
+        SO IM LIKE getImageParams WITH UR $handler\r
+                IZ $handler\r
+                        I HAS handlerClass IZ get_class( $handler )\r
+                NOWAI\r
+                        I HAS handlerClass IZ ''\r
+                KTHX\r
+                IZ !isset( $this->mImageParams[$handlerClass]  )\r
+                        BTW Initialise static lists\r
+                       static $internalParamNames = array(\r
+                               'horizAlign' => array( 'left', 'right', 'center', 'none' ),\r
+                               'vertAlign' => array( 'baseline', 'sub', 'super', 'top', 'text-top', 'middle',\r
+                                       'bottom', 'text-bottom' ),\r
+                               'frame' => array( 'thumbnail', 'manualthumb', 'framed', 'frameless',\r
+                                       'upright', 'border', 'link', 'alt' ),\r
+                        BUCKET\r
+                       static $internalParamMap;\r
+                        IZ !$internalParamMap\r
+                                I HAS internalParamMap IZ EMPTY\r
+                                IM IN UR internalParamNames ITZA type => $names\r
+                                        IM IN UR names ITZA name\r
+                                                I HAS magicName IZ str_replace( '-', '_', "img_$name" )\r
+                                               $internalParamMap[$magicName] = array( $type, $name );\r
+                                        KTHX\r
+                                KTHX\r
+                        KTHX\r
+\r
+                        BTW Add handler params\r
+                        I HAS paramMap IZ $internalParamMap\r
+                        IZ $handler\r
+                                I HAS handlerParamMap IZ $handler->getParamMap()\r
+                                IM IN UR handlerParamMap ITZA magic => $paramName\r
+                                       $paramMap[$magic] = array( 'handler', $paramName );\r
+                                KTHX\r
+                        KTHX\r
+                       $this->mImageParams[$handlerClass] = $paramMap;\r
+                       $this->mImageParamsMagicArray[$handlerClass] = new MagicWordArray( array_keys( $paramMap ) );\r
+                KTHX\r
+                I FOUND MAH array( $this->mImageParams[$handlerClass], $this->mImageParamsMagicArray[$handlerClass] )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Parse image options text and use it to make an image\r
+         NOT WANT @param Title $title\r
+         NOT WANT @param string $options\r
+         NOT WANT @param LinkHolderArray $holders\r
+         WANT\r
+        SO IM LIKE makeImage WITH UR $title, $options, $holders = false\r
+                BTW Check if the options text is of the form "options|alt text"\r
+                BTW Options are:\r
+                BTW  * thumbnail  make a thumbnail with enlarge-icon and caption, alignment depends on lang\r
+                BTW  * left       no resizing, just left align. label is used for alt= only\r
+                BTW  * right      same, but right aligned\r
+                BTW  * none       same, but not aligned\r
+                BTW  * ___px      scale to ___ pixels width, no aligning. e.g. use in taxobox\r
+                BTW  * center     center the image\r
+                BTW  * frame      Keep original image size, no magnify-button.\r
+                BTW  * framed     Same as "frame"\r
+                BTW  * frameless  like 'thumb' but without a frame. Keeps user preferences for width\r
+                BTW  * upright    reduce width for upright images, rounded to full __0 px\r
+                BTW  * border     draw a 1px border around the image\r
+                BTW  * alt        Text for HTML alt attribute (defaults to empty)\r
+                BTW  * link       Set the target of the image link. Can be external, interwiki, or local\r
+                BTW vertical-align values (no % or length right now):\r
+                BTW  * baseline\r
+                BTW  * sub\r
+                BTW  * super\r
+                BTW  * top\r
+                BTW  * text-top\r
+                BTW  * middle\r
+                BTW  * bottom\r
+                BTW  * text-bottom\r
+\r
+                I HAS parts IZ StringUtils::explode( "|", $options )\r
+                I HAS sk IZ $this->mOptions->getSkin()\r
+\r
+                BTW Give extensions a chance to select the file revision for us\r
+                I HAS skip IZ $time = $descQuery = false\r
+                IM ON UR wfRunHooks DOING 'BeforeParserMakeImageLinkObj', array( &$this, &$title, &$skip, &$time, &$descQuery )\r
+\r
+                IZ $skip\r
+                        I FOUND MAH $sk->link( $title )\r
+                KTHX\r
+\r
+                BTW Get the file\r
+                I HAS imagename IZ $title->getDBkey()\r
+                I HAS file IZ wfFindFile( $title, array( 'time' => $time ) )\r
+                BTW Get parameter map\r
+                I HAS handler IZ $file ? $file->getHandler() : false\r
+\r
+                IM ON UR list DOING $paramMap, $mwArray ) = $this->getImageParams( $handler\r
+\r
+                BTW Process the input parameters\r
+                I HAS caption IZ ''\r
+                I HAS params IZ BUCKET 'frame' => array(), 'handler' => array(),\r
+                       'horizAlign' => array(), 'vertAlign' => array() );\r
+                IM IN UR parts ITZA part\r
+                        I HAS part IZ trim( $part )\r
+                        IM ON UR list DOING $magicName, $value ) = $mwArray->matchVariableStartToEnd( $part\r
+                        I HAS validated IZ false\r
+                        IZ isset( $paramMap[$magicName] )\r
+                               list( $type, $paramName ) = $paramMap[$magicName];\r
+\r
+                                BTW Special case; width and height come in one variable together\r
+                                IZ $type === 'handler' && $paramName === 'width'\r
+                                        I HAS m IZ EMPTY\r
+                                        BTW (bug 13500) In both cases (width/height and width only),\r
+                                        BTW permit trailing "px" for backward compatibility.\r
+                                        IZ preg_match( '/^([0-9]*)x([0-9]*)\s*(?:px)?\s*$/', $value, $m )\r
+                                                I HAS width IZ intval( $m[1] )\r
+                                                I HAS height IZ intval( $m[2] )\r
+                                                IZ $handler->validateParam( 'width', $width )\r
+                                                       $params[$type]['width'] = $width;\r
+                                                        I HAS validated IZ true\r
+                                                KTHX\r
+                                                IZ $handler->validateParam( 'height', $height )\r
+                                                       $params[$type]['height'] = $height;\r
+                                                        I HAS validated IZ true\r
+                                                KTHX\r
+                                        ORLY preg_match( '/^[0-9]*\s*(?:px)?\s*$/', $value )\r
+                                                I HAS width IZ intval( $value )\r
+                                                IZ $handler->validateParam( 'width', $width )\r
+                                                       $params[$type]['width'] = $width;\r
+                                                        I HAS validated IZ true\r
+                                                KTHX\r
+                                        KTHX # else no validation -- bug 13436\r
+                                NOWAI\r
+                                        IZ $type === 'handler'\r
+                                                BTW Validate handler parameter\r
+                                                I HAS validated IZ $handler->validateParam( $paramName, $value )\r
+                                        NOWAI\r
+                                                BTW Validate internal parameters\r
+                                               switch( $paramName ) {\r
+                                               case 'manualthumb':\r
+                                               case 'alt':\r
+                                                        BTW @todo Fixme: possibly check validity here for\r
+                                                        BTW manualthumb? downstream behavior seems odd with\r
+                                                        BTW missing manual thumbs.\r
+                                                        I HAS validated IZ true\r
+                                                        I HAS value IZ $this->stripAltText( $value, $holders )\r
+                                                       break;\r
+                                               case 'link':\r
+                                                        I HAS chars IZ self::EXT_LINK_URL_CLASS\r
+                                                        I HAS prots IZ $this->mUrlProtocols\r
+                                                        IZ $value === ''\r
+                                                                I HAS paramName IZ 'no-link'\r
+                                                                I HAS value IZ true\r
+                                                                I HAS validated IZ true\r
+                                                        ORLY preg_match( "/^$prots/", $value )\r
+                                                                IZ preg_match( "/^($prots)$chars+$/", $value, $m )\r
+                                                                        I HAS paramName IZ 'link-url'\r
+                                                                        IM ON UR SPECIAL mOutput->addExternalLink DOING $value\r
+                                                                        I HAS validated IZ true\r
+                                                                KTHX\r
+                                                        NOWAI\r
+                                                                I HAS linkTitle IZ Title::newFromText( $value )\r
+                                                                IZ $linkTitle\r
+                                                                        I HAS paramName IZ 'link-title'\r
+                                                                        I HAS value IZ $linkTitle\r
+                                                                        IM ON UR SPECIAL mOutput->addLink DOING $linkTitle\r
+                                                                        I HAS validated IZ true\r
+                                                                KTHX\r
+                                                        KTHX\r
+                                                       break;\r
+                                               default:\r
+                                                        BTW Most other things appear to be empty or numeric...\r
+                                                        I HAS validated IZ ( $value === false || is_numeric( trim( $value ) ) )\r
+                                                KTHX\r
+                                        KTHX\r
+\r
+                                        IZ $validated\r
+                                               $params[$type][$paramName] = $value;\r
+                                        KTHX\r
+                                KTHX\r
+                        KTHX\r
+                        IZ !$validated\r
+                                I HAS caption IZ $part\r
+                        KTHX\r
+                KTHX\r
+\r
+                BTW Process alignment parameters\r
+                IZ $params['horizAlign']\r
+                       $params['frame']['align'] = key( $params['horizAlign'] );\r
+                KTHX\r
+                IZ $params['vertAlign']\r
+                       $params['frame']['valign'] = key( $params['vertAlign'] );\r
+                KTHX\r
+\r
+               $params['frame']['caption'] = $caption;\r
+\r
+                BTW Will the image be presented in a frame, with the caption below?\r
+                imageIsFramed IZ isset( $params['frame']['frame'] ) ||\r
+                                isset( $params['frame']['framed'] ) ||\r
+                                isset( $params['frame']['thumbnail'] ) ||\r
+                                 IM ON UR isset DOING $params['frame']['manualthumb']\r
+\r
+                BTW In the old days, [[Image:Foo|text...]] would set alt text.  Later it\r
+                BTW came to also set the caption, ordinary text after the image -- which\r
+                BTW makes no sense, because that just repeats the text multiple times in\r
+                BTW screen readers.  It *also* came to set the title attribute.\r
+                BTW \r
+                BTW Now that we have an alt attribute, we should not set the alt text to\r
+                BTW equal the caption: that's worse than useless, it just repeats the\r
+                BTW text.  This is the framed/thumbnail case.  If there's no caption, we\r
+                BTW use the unnamed parameter for alt text as well, just for the time be-\r
+                BTW ing, if the unnamed param is set and the alt param is not.\r
+                BTW \r
+                BTW For the future, we need to figure out if we want to tweak this more,\r
+                BTW e.g., introducing a title= parameter for the title; ignoring the un-\r
+                BTW named parameter entirely for images without a caption; adding an ex-\r
+                BTW plicit caption= parameter and preserving the old magic unnamed para-\r
+                BTW meter for BC; ...\r
+                IZ $imageIsFramed # Framed image\r
+                        IZ $caption === '' && !isset( $params['frame']['alt'] )\r
+                                BTW No caption or alt text, add the filename as the alt text so\r
+                                BTW that screen readers at least get some description of the image\r
+                               $params['frame']['alt'] = $title->getText();\r
+                        KTHX\r
+                        BTW Do not set $params['frame']['title'] because tooltips don't make sense\r
+                        BTW for framed images\r
+                NOWAI # Inline image\r
+                        IZ !isset( $params['frame']['alt'] )\r
+                                BTW No alt text, use the "caption" for the alt text\r
+                               if ( $caption !== '') {\r
+                                       $params['frame']['alt'] = $this->stripAltText( $caption, $holders );\r
+                                NOWAI\r
+                                        BTW No caption, fall back to using the filename for the\r
+                                        BTW alt text\r
+                                       $params['frame']['alt'] = $title->getText();\r
+                                KTHX\r
+                        KTHX\r
+                        BTW Use the "caption" for the tooltip text\r
+                       $params['frame']['title'] = $this->stripAltText( $caption, $holders );\r
+                KTHX\r
+\r
+                IM ON UR wfRunHooks DOING 'ParserMakeImageParams', array( $title, $file, &$params )\r
+\r
+                BTW Linker does the rest\r
+                I HAS ret IZ $sk->makeImageLink2( $title, $file, $params['frame'], $params['handler'], $time, $descQuery )\r
+\r
+                BTW Give the handler a chance to modify the parser object\r
+                IZ $handler\r
+                       $handler->parserTransformHook( $this, $file );\r
+                KTHX\r
+\r
+                I FOUND MAH $ret\r
+        KTHX\r
+\r
+        SO IM LIKE stripAltText WITH UR $caption, $holders\r
+                BTW Strip bad stuff out of the title (tooltip).  We can't just use\r
+                BTW replaceLinkHoldersText() here, because if this function is called\r
+                BTW from replaceInternalLinks2(), mLinkHolders won't be up-to-date.\r
+                IZ $holders\r
+                        I HAS tooltip IZ $holders->replaceText( $caption )\r
+                NOWAI\r
+                        I HAS tooltip IZ $this->replaceLinkHoldersText( $caption )\r
+                KTHX\r
+\r
+                BTW make sure there are no placeholders in thumbnail attributes\r
+                BTW that are later expanded to html- so expand them now and\r
+                BTW remove the tags\r
+                I HAS tooltip IZ $this->mStripState->unstripBoth( $tooltip )\r
+                I HAS tooltip IZ Sanitizer::stripAllTags( $tooltip )\r
+\r
+                I FOUND MAH $tooltip\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Set a flag in the output object indicating that the content is dynamic and\r
+         NOT WANT shouldn't be cached.\r
+         WANT\r
+        SO IM LIKE disableCache\r
+                IM ON UR wfDebug DOING "Parser output marked as uncacheable.\n"\r
+                UR SPECIAL mOutput->mCacheTime IZ -1;\r
+        KTHX\r
+\r
+        DO NOT WANT#@+\r
+         NOT WANT Callback from the Sanitizer for expanding items found in HTML attribute\r
+         NOT WANT values, so they can be safely tested and escaped.\r
+         NOT WANT @param string $text\r
+         NOT WANT @param PPFrame $frame\r
+         NOT WANT @return string\r
+         NOT WANT @private\r
+         WANT\r
+        SO IM LIKE attributeStripCallback WITH UR &$text, $frame = false\r
+                I HAS text IZ $this->replaceVariables( $text, $frame )\r
+                I HAS text IZ $this->mStripState->unstripBoth( $text )\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        DO NOT WANT#@-*/\r
+\r
+        DO NOT WANT#@+\r
+         NOT WANT Accessor/mutator\r
+         WANT\r
+        SO IM LIKE Title WITH UR $x = null TESTING UR return wfSetVar( $this->mTitle, $x );\r
+        SO IM LIKE Options WITH UR $x = null TESTING UR return wfSetVar( $this->mOptions, $x );\r
+        SO IM LIKE OutputType WITH UR $x = null TESTING UR return wfSetVar( $this->mOutputType, $x );\r
+        DO NOT WANT#@-*/\r
+\r
+        DO NOT WANT#@+\r
+         NOT WANT Accessor\r
+         WANT\r
+        SO IM LIKE getTags \r
+                I FOUND MAH array_merge( array_keys( $this->mTransparentTagHooks ), array_keys( $this->mTagHooks ) ) \r
+        KTHX\r
+        DO NOT WANT#@-*/\r
+\r
+\r
+        DO NOT WANT\r
+         NOT WANT Break wikitext input into sections, and either pull or replace\r
+         NOT WANT some particular section's text.\r
+         NOT WANT \r
+         NOT WANT External callers should use the getSection and replaceSection methods.\r
+         NOT WANT \r
+         NOT WANT @param string $text Page wikitext\r
+         NOT WANT @param string $section A section identifier string of the form:\r
+         NOT WANT   <flag1> - <flag2> - ... - <section number>\r
+         NOT WANT \r
+         NOT WANT Currently the only recognised flag is "T", which means the target section number\r
+         NOT WANT was derived during a template inclusion parse, in other words this is a template\r
+         NOT WANT section edit link. If no flags are given, it was an ordinary section edit link.\r
+         NOT WANT This flag is required to avoid a section numbering mismatch when a section is\r
+         NOT WANT enclosed by <includeonly> (bug 6563).\r
+         NOT WANT \r
+         NOT WANT The section number 0 pulls the text before the first heading; other numbers will\r
+         NOT WANT pull the given section along with its lower-level subsections. If the section is\r
+         NOT WANT not found, $mode=get will return $newtext, and $mode=replace will return $text.\r
+         NOT WANT \r
+         NOT WANT @param string $mode One of "get" or "replace"\r
+         NOT WANT @param string $newText Replacement text for section data.\r
+         NOT WANT @return string for "get", the extracted section text.\r
+         NOT WANT                for "replace", the whole page with the section replaced.\r
+         WANT\r
+        SO IM LIKE extractSections WITH UR $text, $section, $mode, $newText=''\r
+                I HAS UR $wgTitle ON UR INTERNETS\r
+                IM ON UR SPECIAL clearState\r
+                IM ON UR SPECIAL setTitle DOING $wgTitle # not generally used but removes an ugly failure mode\r
+                UR SPECIAL mOptions IZ new ParserOptions;\r
+                IM ON UR SPECIAL setOutputType DOING self::OT_PLAIN\r
+                I HAS outText IZ ''\r
+                I HAS frame IZ $this->getPreprocessor()->newFrame()\r
+\r
+                BTW Process section extraction flags\r
+                I HAS flags IZ 0\r
+                I HAS sectionParts IZ explode( '-', $section )\r
+                I HAS sectionIndex IZ array_pop( $sectionParts )\r
+                IM IN UR sectionParts ITZA part\r
+                        IZ $part === 'T'\r
+                               $flags |= self::PTD_FOR_INCLUSION;\r
+                        KTHX\r
+                KTHX\r
+                BTW Preprocess the text\r
+                I HAS root IZ $this->preprocessToDom( $text, $flags )\r
+\r
+                BTW <h> nodes indicate section breaks\r
+                BTW They can only occur at the top level, so we can find them by iterating the root's children\r
+                I HAS node IZ $root->getFirstChild()\r
+\r
+                BTW Find the target section\r
+                IZ $sectionIndex == 0\r
+                        BTW Section zero doesn't nest, level=big\r
+                        I HAS targetLevel IZ 1000\r
+                NOWAI\r
+             STEALIN UR $node\r
+                 IZ $node->getName() === 'h'\r
+                     I HAS bits IZ $node->splitHeading()\r
+                                        IZ $bits['i'] == $sectionIndex\r
+                                        I HAS targetLevel IZ $bits['level']\r
+                                               break;\r
+                                        KTHX\r
+                                KTHX\r
+                                IZ $mode === 'replace'\r
+                                        outText HAS MOAR $frame->expand( $node, PPFrame::RECOVER_ORIG );\r
+                                KTHX\r
+                                I HAS node IZ $node->getNextSibling()\r
+                        KTHX\r
+                KTHX\r
+\r
+                IZ !$node\r
+                        BTW Not found\r
+                        IZ $mode === 'get'\r
+                                I FOUND MAH $newText\r
+                        NOWAI\r
+                                I FOUND MAH $text\r
+                        KTHX\r
+                KTHX\r
+\r
+                BTW Find the end of the section, including nested sections\r
+               do {\r
+                        IZ $node->getName() === 'h'\r
+                                I HAS bits IZ $node->splitHeading()\r
+                                I HAS curLevel IZ $bits['level']\r
+                                IZ $bits['i'] != $sectionIndex && $curLevel <= $targetLevel\r
+                                       break;\r
+                                KTHX\r
+                        KTHX\r
+                        IZ $mode === 'get'\r
+                                outText HAS MOAR $frame->expand( $node, PPFrame::RECOVER_ORIG );\r
+                        KTHX\r
+                        I HAS node IZ $node->getNextSibling()\r
+                KTHX while ( $node );\r
+\r
+                BTW Write out the remainder (in replace mode only)\r
+                IZ $mode === 'replace'\r
+                        BTW Output the replacement text\r
+                        BTW Add two newlines on -- trailing whitespace in $newText is conventionally\r
+                        BTW stripped by the editor, so we need both newlines to restore the paragraph gap\r
+                        BTW Only add trailing whitespace if there is newText\r
+                        IZ $newText != ""\r
+                                outText HAS MOAR $newText . "\n\n";\r
+                        KTHX\r
+\r
+                        STEALIN UR $node\r
+                                outText HAS MOAR $frame->expand( $node, PPFrame::RECOVER_ORIG );\r
+                                I HAS node IZ $node->getNextSibling()\r
+                        KTHX\r
+                KTHX\r
+\r
+                IZ is_string( $outText )\r
+                        BTW Re-insert stripped tags\r
+                        I HAS outText IZ rtrim( $this->mStripState->unstripBoth( $outText ) )\r
+                KTHX\r
+\r
+                I FOUND MAH $outText\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT This function returns the text of a section, specified by a number ($section).\r
+         NOT WANT A section is text under a heading like == Heading == or \<h1\>Heading\</h1\>, or\r
+         NOT WANT the first section before any such heading (section 0).\r
+         NOT WANT \r
+         NOT WANT If a section contains subsections, these are also returned.\r
+         NOT WANT \r
+         NOT WANT @param string $text text to look in\r
+         NOT WANT @param string $section section identifier\r
+         NOT WANT @param string $deftext default to return if section is not found\r
+         NOT WANT @return string text of the requested section\r
+         WANT\r
+        SO IM LIKE getSection WITH UR $text, $section, $deftext=''\r
+                I FOUND MAH $this->extractSections( $text, $section, "get", $deftext )\r
+        KTHX\r
+\r
+        SO IM LIKE replaceSection WITH UR $oldtext, $section, $text\r
+                I FOUND MAH $this->extractSections( $oldtext, $section, "replace", $text )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Get the timestamp associated with the current revision, adjusted for\r
+         NOT WANT the default server-local timestamp\r
+         WANT\r
+        SO IM LIKE getRevisionTimestamp\r
+                IZ is_null( $this->mRevisionTimestamp )\r
+                        IM ON UR wfProfileIn DOING __METHOD__\r
+                        I HAS UR $wgContLang ON UR INTERNETS\r
+                        I HAS dbr IZ wfGetDB( DB_SLAVE )\r
+                        timestamp IZ $dbr->selectField( 'revision', 'rev_timestamp',\r
+                                        IM ON UR array DOING 'rev_id' => $this->mRevisionId ), __METHOD__\r
+\r
+                        BTW Normalize timestamp to internal MW format for timezone processing.\r
+                        BTW This has the added side-effect of replacing a null value with\r
+                        BTW the current time, which gives us more sensible behavior for\r
+                        BTW previews.\r
+                        I HAS timestamp IZ wfTimestamp( TS_MW, $timestamp )\r
+\r
+                        BTW The cryptic '' timezone parameter tells to use the site-default\r
+                        BTW timezone offset instead of the user settings.\r
+                        BTW \r
+                        BTW Since this value will be saved into the parser cache, served\r
+                        BTW to other users, and potentially even used inside links and such,\r
+                        BTW it needs to be consistent for all visitors.\r
+                        UR SPECIAL mRevisionTimestamp IZ $wgContLang->userAdjust( $timestamp, '' );\r
+\r
+                        IM ON UR wfProfileOut DOING __METHOD__\r
+                KTHX\r
+                I FOUND MAH $this->mRevisionTimestamp\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Get the name of the user that edited the last revision\r
+         WANT\r
+        SO IM LIKE getRevisionUser\r
+                BTW if this template is subst: the revision id will be blank,\r
+                BTW so just use the current user's name\r
+                IZ $this->mRevisionId\r
+                        I HAS revision IZ Revision::newFromId( $this->mRevisionId )\r
+                        I HAS revuser IZ $revision->getUserText()\r
+                NOWAI\r
+                        I HAS UR $wgUser ON UR INTERNETS\r
+                        I HAS revuser IZ $wgUser->getName()\r
+                KTHX\r
+                I FOUND MAH $revuser\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Mutator for $mDefaultSort\r
+         NOT WANT \r
+         NOT WANT @param $sort New value\r
+         WANT\r
+        SO IM LIKE setDefaultSort WITH UR $sort\r
+                UR SPECIAL mDefaultSort IZ $sort;\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Accessor for $mDefaultSort\r
+         NOT WANT Will use the title/prefixed title if none is set\r
+         NOT WANT \r
+         NOT WANT @return string\r
+         WANT\r
+        SO IM LIKE getDefaultSort\r
+                I HAS UR $wgCategoryPrefixedDefaultSortkey ON UR INTERNETS\r
+                IZ $this->mDefaultSort !== false\r
+                        I FOUND MAH $this->mDefaultSort\r
+                KTHX elseif ( $this->mTitle->getNamespace() == NS_CATEGORY ||\r
+                       !$wgCategoryPrefixedDefaultSortkey ) \r
+               {\r
+                        I FOUND MAH $this->mTitle->getText()\r
+                NOWAI\r
+                        I FOUND MAH $this->mTitle->getPrefixedText()\r
+                KTHX\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Accessor for $mDefaultSort\r
+         NOT WANT Unlike getDefaultSort(), will return false if none is set\r
+         NOT WANT \r
+         NOT WANT @return string or false\r
+         WANT\r
+        SO IM LIKE getCustomDefaultSort\r
+                I FOUND MAH $this->mDefaultSort\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Try to guess the section anchor name based on a wikitext fragment\r
+         NOT WANT presumably extracted from a heading, for example "Header" from\r
+         NOT WANT "== Header ==".\r
+         WANT\r
+        SO IM LIKE guessSectionNameFromWikiText WITH UR $text\r
+                BTW Strip out wikitext links(they break the anchor)\r
+                I HAS text IZ $this->stripSectionName( $text )\r
+                I HAS headline IZ Sanitizer::decodeCharReferences( $text )\r
+                BTW strip out HTML\r
+                I HAS headline IZ StringUtils::delimiterReplace( '<', '>', '', $headline )\r
+                I HAS headline IZ trim( $headline )\r
+                I HAS sectionanchor IZ '#' . urlencode( str_replace( ' ', '_', $headline ) )\r
+                I HAS replacearray IZ BUCKET\r
+                       '%3A' => ':',\r
+                       '%' => '.'\r
+                BUCKET\r
+               return str_replace(\r
+                       array_keys( $replacearray ),\r
+                       array_values( $replacearray ),\r
+                       $sectionanchor );\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT Strips a text string of wikitext for use in a section anchor\r
+         NOT WANT \r
+         NOT WANT Accepts a text string and then removes all wikitext from the\r
+         NOT WANT string and leaves only the resultant text (i.e. the result of\r
+         NOT WANT [[User:WikiSysop|Sysop]] would be "Sysop" and the result of\r
+         NOT WANT [[User:WikiSysop]] would be "User:WikiSysop") - this is intended\r
+         NOT WANT to create valid section anchors by mimicing the output of the\r
+         NOT WANT parser when headings are parsed.\r
+         NOT WANT \r
+         NOT WANT @param $text string Text string to be stripped of wikitext\r
+         NOT WANT for use in a Section anchor\r
+         NOT WANT @return Filtered text string\r
+         WANT\r
+        SO IM LIKE stripSectionName WITH UR $text\r
+                BTW Strip internal link markup\r
+                I HAS text IZ preg_replace( '/\[\[:?([^[|]+)\|([^[]+)\]\]/', '$2', $text )\r
+                I HAS text IZ preg_replace( '/\[\[:?([^[]+)\|?\]\]/', '$1', $text )\r
+\r
+                BTW Strip external link markup (FIXME: Not Tolerant to blank link text\r
+                BTW I.E. [http://www.mediawiki.org] will render as [1] or something depending\r
+                BTW on how many empty links there are on the page - need to figure that out.\r
+                I HAS text IZ preg_replace( '/\[(?:' . wfUrlProtocols() . ')([^ ]+?) ([^[]+)\]/', '$2', $text )\r
+\r
+                BTW Parse wikitext quotes (italics & bold)\r
+                I HAS text IZ $this->doQuotes( $text )\r
+\r
+                BTW Strip HTML tags\r
+                I HAS text IZ StringUtils::delimiterReplace( '<', '>', '', $text )\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        SO IM LIKE srvus WITH UR $text\r
+                I FOUND MAH $this->testSrvus( $text, $this->mOutputType )\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT strip/replaceVariables/unstrip for preprocessor regression testing\r
+         WANT\r
+        SO IM LIKE testSrvus WITH UR $text, $title, $options, $outputType = self::OT_HTML\r
+                IM ON UR SPECIAL clearState\r
+                IZ !$title instanceof Title\r
+                        I HAS title IZ Title::newFromText( $title )\r
+                KTHX\r
+                UR SPECIAL mTitle IZ $title;\r
+                UR SPECIAL mOptions IZ $options;\r
+                IM ON UR SPECIAL setOutputType DOING $outputType\r
+                I HAS text IZ $this->replaceVariables( $text )\r
+                I HAS text IZ $this->mStripState->unstripBoth( $text )\r
+                I HAS text IZ Sanitizer::removeHTMLtags( $text )\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        SO IM LIKE testPst WITH UR $text, $title, $options\r
+                I HAS UR $wgUser ON UR INTERNETS\r
+                IZ !$title instanceof Title\r
+                        I HAS title IZ Title::newFromText( $title )\r
+                KTHX\r
+                I FOUND MAH $this->preSaveTransform( $text, $title, $wgUser, $options )\r
+        KTHX\r
+\r
+        SO IM LIKE testPreprocess WITH UR $text, $title, $options\r
+                IZ !$title instanceof Title\r
+                        I HAS title IZ Title::newFromText( $title )\r
+                KTHX\r
+                I FOUND MAH $this->testSrvus( $text, $title, $options, self::OT_PREPROCESS )\r
+        KTHX\r
+\r
+        SO IM LIKE markerSkipCallback WITH UR $s, $callback\r
+                I HAS i IZ 0\r
+                I HAS out IZ ''\r
+                STEALIN UR $i < strlen( $s )\r
+                        I HAS markerStart IZ strpos( $s, $this->mUniqPrefix, $i )\r
+                        IZ $markerStart === false\r
+                                out HAS MOAR call_user_func( $callback, substr( $s, $i ) );\r
+                               break;\r
+                        NOWAI\r
+                                out HAS MOAR call_user_func( $callback, substr( $s, $i, $markerStart - $i ) );\r
+                                I HAS markerEnd IZ strpos( $s, self::MARKER_SUFFIX, $markerStart )\r
+                                IZ $markerEnd === false\r
+                                        out HAS MOAR substr( $s, $markerStart );\r
+                                       break;\r
+                                NOWAI\r
+                                       $markerEnd += strlen( self::MARKER_SUFFIX );\r
+                                        out HAS MOAR substr( $s, $markerStart, $markerEnd - $markerStart );\r
+                                        I HAS i IZ $markerEnd\r
+                                KTHX\r
+                        KTHX\r
+                KTHX\r
+                I FOUND MAH $out\r
+        KTHX\r
+\r
+        SO IM LIKE serialiseHalfParsedText WITH UR $text\r
+                I HAS data IZ EMPTY\r
+               $data['text'] = $text;\r
+\r
+                BTW First, find all strip markers, and store their\r
+                BTW  data in an array.\r
+                I HAS stripState IZ new StripState\r
+                I HAS pos IZ 0\r
+               while ( ( $start_pos = strpos( $text, $this->mUniqPrefix, $pos ) ) \r
+                       && ( $end_pos = strpos( $text, self::MARKER_SUFFIX, $pos ) ) ) \r
+               {\r
+                       $end_pos += strlen( self::MARKER_SUFFIX );\r
+                        I HAS marker IZ substr( $text, $start_pos, $end_pos-$start_pos )\r
+\r
+                        IZ !empty( $this->mStripState->general->data[$marker] )\r
+                                I HAS replaceArray IZ $stripState->general\r
+                                I HAS stripText IZ $this->mStripState->general->data[$marker]\r
+                        ORLY !empty( $this->mStripState->nowiki->data[$marker] )\r
+                                I HAS replaceArray IZ $stripState->nowiki\r
+                                I HAS stripText IZ $this->mStripState->nowiki->data[$marker]\r
+                        NOWAI\r
+                               throw new MWException( "Hanging strip marker: '$marker'." );\r
+                        KTHX\r
+\r
+                       $replaceArray->setPair( $marker, $stripText );\r
+                        I HAS pos IZ $end_pos\r
+                KTHX\r
+               $data['stripstate'] = $stripState;\r
+\r
+                BTW Now, find all of our links, and store THEIR\r
+                BTW  data in an array! :)\r
+                I HAS links IZ BUCKET 'internal' => array(), 'interwiki' => array() );\r
+                I HAS pos IZ 0\r
+\r
+                BTW Internal links\r
+                STEALIN UR ( $start_pos = strpos( $text, '<!--LINK ', $pos ) )\r
+                        IM ON UR list DOING $ns, $trail ) = explode( ':', substr( $text, $start_pos + strlen( '<!--LINK ' ) ), 2\r
+\r
+                        I HAS ns IZ trim( $ns )\r
+                        IZ empty( $links['internal'][$ns] )\r
+                               $links['internal'][$ns] = array();\r
+                        KTHX\r
+\r
+                        I HAS key IZ trim( substr( $trail, 0, strpos( $trail, '-->' ) ) )\r
+                       $links['internal'][$ns][] = $this->mLinkHolders->internals[$ns][$key];\r
+                        I HAS pos IZ $start_pos + strlen( "<!--LINK $ns:$key-->" )\r
+                KTHX\r
+\r
+                I HAS pos IZ 0\r
+\r
+                BTW Interwiki links\r
+                STEALIN UR ( $start_pos = strpos( $text, '<!--IWLINK ', $pos ) )\r
+                        I HAS data IZ substr( $text, $start_pos )\r
+                        I HAS key IZ trim( substr( $data, 0, strpos( $data, '-->' ) ) )\r
+                       $links['interwiki'][] = $this->mLinkHolders->interwiki[$key];\r
+                        I HAS pos IZ $start_pos + strlen( "<!--IWLINK $key-->" )\r
+                KTHX\r
+\r
+               $data['linkholder'] = $links;\r
+\r
+                I FOUND MAH $data\r
+        KTHX\r
+\r
+        DO NOT WANT\r
+         NOT WANT TODO: document\r
+         NOT WANT @param $data Array\r
+         NOT WANT @param $intPrefix String unique identifying prefix\r
+         NOT WANT @return String\r
+         WANT\r
+        SO IM LIKE unserialiseHalfParsedText WITH UR $data, $intPrefix = null\r
+                IZ !$intPrefix\r
+                        I HAS intPrefix IZ $this->getRandomString()\r
+                KTHX\r
+\r
+                BTW First, extract the strip state.\r
+                I HAS stripState IZ $data['stripstate']\r
+                IM ON UR SPECIAL mStripState->general->merge DOING $stripState->general\r
+                IM ON UR SPECIAL mStripState->nowiki->merge DOING $stripState->nowiki\r
+\r
+                BTW Now, extract the text, and renumber links\r
+                I HAS text IZ $data['text']\r
+                I HAS links IZ $data['linkholder']\r
+\r
+                BTW Internal...\r
+               foreach ( $links['internal'] as $ns => $nsLinks ) {\r
+                        IM IN UR nsLinks ITZA key => $entry\r
+                                I HAS newKey IZ $intPrefix . '-' . $key\r
+                               $this->mLinkHolders->internals[$ns][$newKey] = $entry;\r
+\r
+                                I HAS text IZ str_replace( "<!--LINK $ns:$key-->", "<!--LINK $ns:$newKey-->", $text )\r
+                        KTHX\r
+                KTHX\r
+\r
+                BTW Interwiki...\r
+               foreach ( $links['interwiki'] as $key => $entry ) {\r
+                        I HAS newKey IZ "$intPrefix-$key"\r
+                       $this->mLinkHolders->interwikis[$newKey] = $entry;\r
+\r
+                        I HAS text IZ str_replace( "<!--IWLINK $key-->", "<!--IWLINK $newKey-->", $text )\r
+                KTHX\r
+\r
+                BTW Should be good to go.\r
+                I FOUND MAH $text\r
+        KTHX\r
+ KTHX\r
+\r
+ DO NOT WANT\r
+  NOT WANT @todo document, briefly.\r
+  NOT WANT @ingroup Parser\r
+  WANT\r
+ IM IN UR SPECIAL StripState\r
+        I HAS UR $general, $nowiki\r
+\r
+        SO IM LIKE __construct\r
+                UR SPECIAL general IZ new ReplacementArray;\r
+                UR SPECIAL nowiki IZ new ReplacementArray;\r
+        KTHX\r
+\r
+        SO IM LIKE unstripGeneral WITH UR $text\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+               do {\r
+                        I HAS oldText IZ $text\r
+                        I HAS text IZ $this->general->replace( $text )\r
+                KTHX while ( $text !== $oldText );\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        SO IM LIKE unstripNoWiki WITH UR $text\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+               do {\r
+                        I HAS oldText IZ $text\r
+                        I HAS text IZ $this->nowiki->replace( $text )\r
+                KTHX while ( $text !== $oldText );\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $text\r
+        KTHX\r
+\r
+        SO IM LIKE unstripBoth WITH UR $text\r
+                IM ON UR wfProfileIn DOING __METHOD__\r
+               do {\r
+                        I HAS oldText IZ $text\r
+                        I HAS text IZ $this->general->replace( $text )\r
+                        I HAS text IZ $this->nowiki->replace( $text )\r
+                KTHX while ( $text !== $oldText );\r
+                IM ON UR wfProfileOut DOING __METHOD__\r
+                I FOUND MAH $text\r
+        KTHX\r
+ KTHX\r
+\r
+ DO NOT WANT\r
+  NOT WANT @todo document, briefly.\r
+  NOT WANT @ingroup Parser\r
+  WANT\r
+ IM IN UR SPECIAL OnlyIncludeReplacer\r
+       var $output = '';\r
+\r
+        SO IM LIKE replace WITH UR $matches\r
+                IZ substr( $matches[1], -1 ) === "\n"\r
+                       $this->output .= substr( $matches[1], 0, -1 );\r
+                NOWAI\r
+                       $this->output .= $matches[1];\r
+                KTHX\r
+        KTHX\r
+ KTHX\r
\ No newline at end of file