Mediawiki: Difference between revisions

From miki
Jump to navigation Jump to search
(→‎Patch v0.2 → v0.3: Fix template)
(→‎Extensions: Move text to dedicated page)
Line 107: Line 107:


== Extensions ==
== Extensions ==
* [[MediaWiki GeSHi]]

* [[MediaWiki RawFile]]
=== SyntaxHighlight GeSHi ===

This extension adds the <tt>&lt;source&gt;</tt> tag to present formatted source code. See official [http://www.mediawiki.org/wiki/Extension:SyntaxHighlight_GeSHi page].

==== Restoring old <tt>&lt;pre&gt;</tt> formatting ====
Since at least version ''r24298 (July 21, 2007)'' (with ''GeSHi version 1.0.8''), <tt>&lt;source&gt;</tt> tag does not match usual formatting applied for <tt>&lt;pre&gt;</tt> tags. This is because the extension applies by default the new GeSHi header style <tt>[http://qbnz.com/highlighter/geshi-doc.html#the-code-container GESHI_HEADER_PRE_VALID]</tt>. We describe below different solutions to restore the old formatting:
<ul>
<li>'''Define a custom style in [[MediaWiki:Common.css]]''' &mdash; This is probably the easiest & safest method, and also it allows to customize the output. For instance the following style adds a left border + background by default, unless if the <code>&lt;source&gt;</code> tag is enclosed in a <code>&lt;div class="noborder"&gt;</code>
<source lang="css">
/** GeSHi Syntax Highlight - custom styles */
/** ... by default, we add a left border + left padding + left margin + lightgray background (for clarity) */
div.mw-geshi
{
margin: 0.5em 0em 0.5em 2em;
padding: 0em 0em 0em 1em;
border-left: 1px dashed #2f6fab;
background-color: #f9f9f9;
}
/** ... except if the <source> tag is enclosed in a <div class="noborder"> */
div.noborder div.mw-geshi
{
margin: 0px;
padding: 0px;
border-left: none;
background-color: inherit;
}
</source>
</li>
<li>'''Patch GeSHi''' &mdash; The following patch restores the old <code>pre</code> format. It also introduces a new option '''<tt>prevalid</tt>''' to attribute <tt>enclose</tt> to force application of header style <tt>GESHI_HEADER_PRE_VALID</tt>.

{{hiddenSourceFile||SyntaxHighlight_GeSHi_r24298.patch|<source lang="diff">
--- SyntaxHighlight_GeSHi.class.php.old 2008-09-07 23:24:37.000000000 +0200
+++ SyntaxHighlight_GeSHi.class.php 2008-09-07 23:33:15.000000000 +0200
@@ -39,7 +39,7 @@
// "Enclose" parameter
if ( isset( $args['enclose'] ) && $args['enclose'] == 'div' ) {
$enclose = GESHI_HEADER_DIV;
- } elseif ( defined('GESHI_HEADER_PRE_VALID') ) {
+ } elseif ( (isset( $args['line'] ) || isset( $args['enclose'] ) && $args['enclose'] == 'prevalid' ) && defined('GESHI_HEADER_PRE_VALID') ) {
// Since version 1.0.8 geshi can produce valid pre, but we need to check for it
$enclose = GESHI_HEADER_PRE_VALID;
} elseif( isset( $args['line'] ) ) {
</source>}}

{{hiddenSourceFile||SyntaxHighlight_GeSHi_r60735.patch|<source lang="diff">
--- SyntaxHighlight_GeSHi.class.php.old 2008-09-07 23:24:37.000000000 +0200
+++ SyntaxHighlight_GeSHi.class.php 2008-09-07 23:33:15.000000000 +0200
@@ -39,7 +39,7 @@
// "Enclose" parameter
if ( isset( $args['enclose'] ) && $args['enclose'] == 'div' ) {
$enclose = GESHI_HEADER_DIV;
- } elseif ( defined('GESHI_HEADER_PRE_VALID') ) {
+ } elseif ( (isset( $args['line'] ) || isset( $args['enclose'] ) && $args['enclose'] == 'prevalid' ) && defined('GESHI_HEADER_PRE_VALID') ) {
// Since version 1.0.8 geshi can produce valid pre, but we need to check for it
$enclose = GESHI_HEADER_PRE_VALID;
} elseif( isset( $args['line'] ) ) {
</source>}}

</li>
<li>'''Add a custom .css to php''' - Another solution is discussed [http://www.mediawiki.org/wiki/Extension_talk:SyntaxHighlight_GeSHi#Problem_with_CSS:_Default_style_for_pre_is_overwritten here]. The proposed solution is to edit file "SyntaxHighlight_GeSHi.class.php". Go to line 192, which should look like
<source lang="php" enclose="prevalid">
$css[] = ".source-$lang {line-height: normal;}";
</source>
Change this to
<source lang="php" enclose="prevalid">
$css[] = ".source-$lang {padding: 1em; border: 1px dashed #2f6fab; color: black; background-color: #f9f9f9; line-height: 1.1em;}";
</source>
and you have restored the pre css formatting.
</li>
</ul>

=== RawFile ===
[http://wiki.yobi.be/wiki/Mediawiki_RawFile RawFile] is an extension made by Philippe Teuwen to allow downloading directly text in <tt>&lt;pre></tt> or <tt>&lt;source></tt> block as a file.

==== Patch v0.2 &rarr; v0.3 ====

The patch below adds an optional parameter to hook <tt><nowiki>{{#filelink}}</nowiki></tt>. With 1 param, the file is fetched from the current page as usual:

<pre>
Save [{{#filelink: fstab}} this file] in your <tt>/etc</tt> directory.
</pre>

With 2 param, the 2nd param is telling which page to fetch the file from:

<pre>
Save [{{#filelink: fstab|Config files - fstab}} this file] in your <tt>/etc</tt> directory.
</pre>

{{hiddenSourceFile||RawFile-v0.2.patch|content=<source lang="diff">
--- original/RawFile.php 2009-09-21 16:20:51.000000000 +0200
+++ patched/RawFile.php 2009-09-21 18:07:06.000000000 +0200
@@ -18,8 +18,12 @@
$magicWords['fileanchor'] = array( 0, 'fileanchor' );
return true;
}
-function efRawFile_Render( &$parser, $filename = '') {
- return $parser->mTitle->getFullURL( 'action=raw&file='.urlencode( $filename ) );
+function efRawFile_Render( &$parser, $filename = '', $titleText = '') {
+ if( $titleText == '' ) {
+ $titleText = $parser->mTitle->getText();
+ }
+ $title=Title::newFromText( $titleText );
+ return $title->getFullURL( 'action=raw&file='.urlencode( $filename ) );
}
function efRawFile_Empty( &$parser, $filename = '') {
return '';
</source>
}}

====Patch v0.3 &rarr; v0.4====
Changes in '''v0.4'''
* '''Anchors''' can be specified using html '''class''' attribute
* New syntax for '''Links''' and '''Anchor-links''':
:<code><nowiki><file [name="..."] [anchor="..."] [tag="..."] [title="..."] >Link text</file></nowiki></code>
* Support multiple files on the same page with same name.
* Can specify the tag name of the block to download (to skip some irrelevant blocks when using an '''anchor-link''').
* Ignore '''<code>&lt;br&gt;</code>''' tag.
* Some error reporting.

The extension introduces 3 elements:
;Anchor
: Used to flag that the next code block in the wiki text belongs to a specific file. The code block can be any wiki block (such as '''<code>&lt;pre&gt;</code>''', '''<code>&lt;code&gt;</code>''', '''<code>&lt;tt&gt;</code>''', '''<code>&lt;source&gt;</code>'''...). '''<code>&lt;br&gt;</code>''' tags are ignored. Note that anchors are invisible in the wiki display.
;Link
: They are transformed by the extension into links that allows for downloading all blocks attached to a given anchor name.
;Anchor-link
: A shortcut notation mixing both an anchor and download link, handy for regular use, when a single code block is used and when the download link can be at the same position as the anchor.

The syntax is as follows. The syntax using tag <code>&lt;file&gt;</code> and tag attribute <code>class</code> is new since v0.4. Note that elements of both syntaxes can be mixed in a same page.
{| border="2" cellspacing="4" cellpadding="3" style="margin: 1em 1em 1em 0; background: #f9f9f9; border: 1px #aaaaaa solid; border-collapse: collapse; empty-cells:show;"
!width="80em" style="background: #8da7d6;"|Element!!style="background: #8da7d6;"|Syntax and description
|-
|'''Anchor'''
|<pre><nowiki>
{{#fileAnchor: anchorname}}
<pre class='anchorname'>...&lt;/pre>
<code class="anchorname">...&lt;/code>
<code class="cssclass anchorname">...&lt;/code>
...
</nowiki></pre>
Indicates that the next wiki block is attached to an anchor ''anchorname''. The content of that block will be downloaded (possibly appended with other blocks if there are several blocks attached to the same ''anchorname'') when a file link is clicked on.<br/>
'''(since v0.4)''' To attach an anchor ''anchorname'' to a wiki block, simply add an attribute <code>class="anchorname"</code> to it. The extension supports multi-class specification, meaning that a same block can be associated to different files, and that the <code>class</code> attribute can still be used to specify custom CSS properties as in standard wiki text.
; ''anchorname''
; class="''anchorname''"
: The name of the anchor to which the wiki block is attached
|-
|'''Link'''
|<pre><nowiki>
[{{#fileLink: anchorname}} link text]
[{{#fileLink: anchorname|pagetitle}} link text]
<file anchor="anchorname" [name="filename"] [title="pagetitle"]>link text</file>
</nowiki></pre>
Creates a link to download all blocks that are attached to an anchor ''anchorname''.
;''anchorname''
;anchor="''anchorname''"
: The name of the anchor to look for. All blocks attached to an anchor ''anchorname'' will be downloaded.
;name="''filename''"
:''Optional'' - Specifies the name of the file to download. If absent, ''anchorname'' is then used as the name of the downloaded file.
; ''pagetitle''
;tag="''pagetitle''"
: ''Optional'' - Indicates that the blocks to download are on the wiki page titled ''pagetitle''. If absent, blocks are looked for on the current page.
; ''link text''
: The text of the link to display.
|-
|'''Anchor-link'''
|<pre><nowiki>
[{{#file: filename}} link text]
<file name="filename" [tag="''tagname''"]>link text</file>
</nowiki></pre>
Creates a link to download the next wiki block as a file named ''filename''.<br/>
'''(since v0.4)''' The attribute <code>tag</code> can be used to specify the ''tagname'' of the block to download.<br>
; ''filename''
; name="''filename''"
: The name of the file to download.
;tag="''tagname''"
:''Optional'' - When set, the extension only looks for blocks whose name matches the given ''tagname''. This attribute is particularly useful when there are some irrelevant blocks between the '''anchor-link''' and the block you want to download. If absent, the first encountered block following the anchor is downloaded.
; ''link text''
: The text of the link to display.
|}

===== Examples =====

<pre><nowiki>
* '''Method 1''': Returns the block that immediately follows. Save [{{#file: method1.txt}} this file]: <code>Hello, World!</code>
: But this other example fails because of the &lt;br&gt; tag... So save [{{#file: method1-fail.txt}} this file]:<br>
:<code>Hello, World!</code>.

* '''Method 2''': Indicates the block(s) with anchors. Save [{{#filelink: method2.txt}} this file] (but not this <code>code text</code>):<br>
:{{#fileanchor: method2.txt}}<code>We can then </code> very easily {{#fileanchor: method2.txt}}<code>interleave downloadable text with wiki comments</code>

* '''Method 3''': Same as above, but using html attribute 'class'. Save [{{#filelink: method3.txt}} this file] (but not this <code>code text</code>):<br>
:{{#fileanchor: method3.txt}}<code>We can still </code> very easily <code class="method3.txt">interleave downloadable text with wiki comments but with less typing</code>
<code class="method3.txt">
Obviously, there is absolutely
no limitation
on the size of the
text
</code>

* '''Method 4''': Same as method 1, but using new syntax (custom wiki tag). Save <file name="method4.txt">'''this''' file</file>: <code>Hello, World!</code>

* '''Method 5''': Same as above, but specifying which tag to include. Save ''<file name="method5.txt" tag="code">this file</file>'':
<source lang="text">This text is skipped.</source>
:<code>This is the text that will be returned...</code>

* '''Method 6''': Same as method 2 / 3, but using new syntax (custom wiki tag). Save <file anchor="method6.txt">this file</file>. Of course the old syntax <code>{{#fileanchor}}</code> for anchor is still supported.<br>
:{{#fileanchor: method6.txt}}<code>Again, we can </code>also very easily <code class="method6.txt">interleave downloadable code with wiki text while using the new syntax</code>
</nowiki></pre>

This gives:

* '''Method 1''': Returns the block that immediately follows. Save [{{#file: method1.txt}} this file]: <code>Hello, World!</code>
: But this other example fails because of the &lt;br&gt; tag... So save [{{#file: method1-fail.txt}} this file]:<br>
:<code>Hello, World!</code>.

* '''Method 2''': Indicates the block(s) with anchors. Save [{{#filelink: method2.txt}} this file] (but not this <code>code text</code>):<br>
:{{#fileanchor: method2.txt}}<code>We can then </code> very easily {{#fileanchor: method2.txt}}<code>interleave downloadable text with wiki comments</code>

* '''Method 3''': Same as above, but using html attribute 'class'. Save [{{#filelink: method3.txt}} this file] (but not this <code>code text</code>):<br>
:{{#fileanchor: method3.txt}}<code>We can still </code> very easily <code class="method3.txt">interleave downloadable text with wiki comments but with less typing</code>
<code class="method3.txt">s
Obviously, there is absolutely
no limitation
on the size of the
text
</code>

* '''Method 4''': Same as method 1, but using new syntax (custom wiki tag). Save <file name="method4.txt">'''this''' file</file>: <code>Hello, World!</code>

* '''Method 5''': Same as above, but specifying which tag to include. Save ''<file name="method5.txt" tag="code">this file</file>'':
<source lang="text">This text is skipped.</source>
:<code>This is the text that will be returned...</code>

* '''Method 6''': Same as method 2 / 3, but using new syntax (custom wiki tag). Save <file anchor="method6.txt">this file</file>. Of course the old syntax <code>{{#fileanchor}}</code> for anchor is still supported.<br>
:{{#fileanchor: method6.txt}}<code>Again, we can </code>also very easily <code class="method6.txt">interleave downloadable code with wiki text while using the new syntax</code>

References:
* [http://www.mediawiki.org/wiki/Manual:Tag_extensions Tag extensions on mediawiki.org]

===== The code =====

{{hiddenSourceFile||RawFile.php|content=<source lang="php">
<?php

if (defined('MEDIAWIKI')) {

//Avoid unstubbing $wgParser on setHook() too early on modern (1.12+) MW versions, as per r35980
if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) {
$wgHooks['ParserFirstCallInit'][] = 'efRawFile_Setup';
} else { // Otherwise do things the old fashioned way
$wgExtensionFunctions[] = 'efRawFile_Setup';
}
$wgHooks['LanguageGetMagic'][] = 'efRawFile_Magic';
$wgHooks['RawPageViewBeforeOutput'][] = 'fnRawFile_Strip';

function efRawFile_Setup() {
global $wgParser;
$wgParser->setFunctionHook( 'file', 'efRawFile_Render' );
$wgParser->setFunctionHook( 'filelink', 'efRawFile_Render' );
$wgParser->setFunctionHook( 'fileanchor', 'efRawFile_Empty' );
$wgParser->setHook( 'file', 'efRawFile_FileTagRender' );
return true;
}

function efRawFile_Magic( &$magicWords, $langCode ) {
$magicWords['file'] = array( 0, 'file' );
$magicWords['filelink'] = array( 0, 'filelink' );
$magicWords['fileanchor'] = array( 0, 'fileanchor' );
return true;
}

function efRawFile_Render( &$parser, $filename = '', $titleText = '') {
if( $titleText == '' )
$title = $parser->mTitle;
else
$title = Title::newFromText( $titleText );
return $title->getFullURL( 'action=raw&anchor='.urlencode( $filename ) );
}

function efRawFile_Empty( &$parser, $filename = '') {
return '';
}

function efRawFile_FileTagRender( $input, $args, &$parser ) {
if( $args['title'] == '' )
$title = $parser->mTitle;
else
$title = Title::newFromText( $args['title'] );
$link=$title->getFullURL( 'action=raw' );
if( $args['name'] != '' )
$link.='&name='.urlencode( $args['name'] );
if( $args['anchor'] != '' )
$link.='&anchor='.urlencode( $args['anchor'] );
if( $args['tag'] != '' )
$link.='&tag='.urlencode( $args['tag'] );
return $parser->recursiveTagParse( "[$link $input]" );
}

function fnRawFile_Strip_Error($msg,$out,&$text) {
$text=$msg;
if($out != '')
$text.="\nCandidate match: $out";
return true;
}

function fnRawFile_Strip(&$rawPage, &$text) {
$filename=$_GET['name'];
$anchor=$_GET['anchor'];
$tag=$_GET['tag'];
// Either anchor or name must be specified
if( $filename=='' )
$filename=$anchor;
if ( $filename=='' )
return true;
// Uncomment the following line to avoid output buffering and gzipping:
// wfResetOutputBuffers();
header("Content-disposition: attachment;filename={$filename}");
header("Content-type: application/octetstream");
header("Content-Transfer-Encoding: binary");
header("Expires: 0");
header("Pragma: no-cache");
header("Cache-Control: no-store");
$maskedtext=preg_replace('!<nowiki>.*?</nowiki>!se',
'preg_replace("/\\\\\\\\\\\'|./","X","$0")',
$text);
if (($anchor!='') && preg_match_all('/({{#fileanchor: *'.$anchor.' *}})|(<[^>]+ class *= *"([^"]*\w)?'.$anchor.'(\w[^"]*)?"[^>]*>)/i', $maskedtext, $matches, PREG_OFFSET_CAPTURE))
$offsets=$matches[0];
else if (preg_match_all('/{{#file: *'.$anchor.' *}}/i', $maskedtext, $matches, PREG_OFFSET_CAPTURE))
$offsets=array($matches[0][0]);
else if (preg_match_all('/<file( [^>]*)? name *= *"'.$filename.'"[^>]*>/i', $maskedtext, $matches, PREG_OFFSET_CAPTURE))
$offsets=array($matches[0][0]);
else {
// We didn't find our anchor
return fnRawFile_Strip_Error("ERROR - RawFile: anchor not found (anchor=$anchor, name=$filename, tag=$tag)","",$text);
}
unset($maskedtext);
$textorig=$text;
$text='';
foreach ($offsets as $offset) {
$out = substr($textorig, $offset[1]);
// If no tag specified, we take the first one
if ($tag == '')
{
// With a regex assertion, we can easily ignore 'br' and 'file' tags
if (!preg_match('/<((?!br\b|file\b)\w+\b)/', $out, $matches))
return fnRawFile_Strip_Error ("ERROR - RawFile: Can't find opening tag after anchor '$offset[0]' (anchor=$anchor, name=$filename, tag=$tag)",$out,$text);
$tag=$matches[1];
}
// Find the first tag matching $tag, and return enclosed text
if (!preg_match('/<'.$tag.'( [^>]*)?>\n?(.*?)<\/'.$tag.'>/s', $out, $matches))
return fnRawFile_Strip_Error ("ERROR - RawFile: no closing '$tag' found after anchor '$offset[0]' (anchor=$anchor, name=$filename, tag=$tag)",$out,$text);
$text .= $matches[2];
}
return true;
}

$wgExtensionCredits['parserhook'][] = array('name' => 'RawFile',
'version' => '0.4',
'author' => 'Philippe Teuwen, Michael Peeters',
'url' => 'http://www.mediawiki.org/wiki/Extension:RawFile',
// 'url' => 'http://wiki.yobi.be/wiki/Mediawiki_RawFile',
'description' => 'Downloads a RAW copy of <nowiki><tag>data</tag></nowiki> in a file<br>'.
'Useful e.g. to download a script or a patch<br>'.
'It also allows what is called [http://en.wikipedia.org/wiki/Literate_programming Literate Programming]');
}

?>
</source>
}}

Revision as of 19:33, 13 February 2014

Hints and Tips

Purge wiki page cache

When changing templates, purge the browser & mediawiki cache. To purge the cache of a single page, add &action=purge to the URL (see [1] for more)

Increase default font size

The easiest way is to add the following to wiki common stylesheet (MediaWiki:Common.css):

/***** Increase default text size ****/
#content {font-size: 1.2em}
body.page-Main_Page #content {font-size: inherit}

The second line overrides effect of first line so that the new font size does not apply to the Main Page.

There are in fact several ways to increase the font size. Using Opera's DragonFly debug environment (Ctrl-Shift-I), it is easy to see how the font size of a normal wiki text is computed (css is filtered for property font-size):

Computed Style
    font-size: 15.36px;

Inherited from div
#bodyContent {
    font-size: 0.8em
}

Inherited from div
#content {
    font-size: larger
}

Inherited from body
body {
    font-size: 1.0em
}

Inherited from html
html {
    font-size: 1.0em
}

Note that em refers to the size of the current font, after application of all inherited styles. In the case above it means that the size of a standard wiki text is not 0.8em as given by div#bodyContent, but well 16px * 1.0 * 1.0 * 1.2 * 0.8 = 15.36px.

One can edit any CSS property above to change the default size of the wiki text. We choose to edit #content so that it only affects the wiki text part (including first header).

Keyboard shortcuts

  • Reference page in wikipedia
  • Page explaining how to change keyboard shortcut using user custom stylesheet.
  • Most frequently-used HTML access keys (default access-key shortcut is alt+shift for Firefox and shift+Esc for Opera):
Action Key
accesskey-edit e
accesskey-preview p
accesskey-save s
accesskey-search f

Access Restriction

See these pages for implementing access restriction in MediaWiki:

  • A page that implement per-page access restriction [2].
  • Another way to hide pages [3].
  • Yet another extension [4].
  • Security problem with access restriction extension:
  • Some information on how to create custom namespaces [7].

Miscellaneous

  • Page Special:Version produces a complete list of all extensions installed on the wiki.

Troubleshooting

Fix templates that always produce {{{1}}}

Templates in Mediawiki will fail if the parameters contains an equal sign. Consider for instance the template nb:

div class="noborder">
{{{1}}}</div>

Let's enclose a <source> tag:

<source lang=bash>echo Hello</source>}}
echo Hello

The fix is simply to prepend 1= to the parameter value:

1=<source lang=bash>echo Hello</source>}}
echo Hello

Development

Tips
  • In 99% of cases, extensions just need to use the method recursiveTagParse of the parser instead of Parser::parse (apparently this function is not re-entrant).

Extensions