aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Code.php41
-rw-r--r--README.md45
-rw-r--r--examples/languages.php3
-rw-r--r--extension.json2
4 files changed, 70 insertions, 21 deletions
diff --git a/Code.php b/Code.php
index 0243e6f..045448e 100644
--- a/Code.php
+++ b/Code.php
@@ -4,10 +4,12 @@ namespace MediaWiki\Extension\Code;
use Content;
use ErrorPageError;
use ExtensionRegistry;
+use FatalError;
use Html;
use MediaWiki\Content\Renderer\ContentParseParams;
use MediaWiki\MediaWikiServices;
use Parser;
+use ParserOptions;
use ParserOutput;
use Sanitizer;
use SpecialPage;
@@ -70,15 +72,6 @@ function renderCode( string $code, $lang, $outputPage, ?array $tagAttrs = null )
$codeBlock = pre( $code, $tagAttrs );
}
- foreach ( $lang['linkifiers'] as $regex => $href ) {
- $codeBlock = preg_replace_callback( $regex, fn( $match ) =>
- Xml::element( 'a', [
- 'href' => str_replace( '$1', $match[0], $href ),
- 'tabindex' => -1
- ], $match[0] ),
- $codeBlock );
- }
-
$actions = '';
foreach ( $lang['actions'] as $action => $url ) {
@@ -96,7 +89,34 @@ function renderCode( string $code, $lang, $outputPage, ?array $tagAttrs = null )
$actions .= Xml::closeElement( 'a' ) . ' ';
}
- return $codeBlock . $actions;
+ $additionalOutput = '';
+
+ $scribuntoModule = $lang['scribuntoModule'] ?? null;
+ if ( $scribuntoModule && ExtensionRegistry::getInstance()->isLoaded( 'Scribunto' ) ) {
+ $callFunction = static function ( Parser $parser, string $function, array $extraArgs = [] ) use ( $scribuntoModule, $code, $lang, $tagAttrs ) {
+ $args = [ $scribuntoModule, $function, $code, $lang['tag'], $tagAttrs == null ];
+ $args = array_merge( $args, $extraArgs );
+ if ( $tagAttrs ) {
+ $args = array_merge( $args, $tagAttrs );
+ }
+ $frame = $parser->getPreprocessor()->newFrame();
+ $res = $parser->callParserFunction( $frame, '#invoke', $args );
+ if ( !$res['found'] ) {
+ throw new FatalError( "unexpected condition in Code extension: the Scribunto module is loaded but the #invoke parser function wasn't found" );
+ }
+ return Sanitizer::removeSomeTags( $res['text'], [ 'extraTags' => [ 'a' ], 'extra' ] );
+ };
+ if ( $tagAttrs ) {
+ $parser = MediaWikiServices::getInstance()->getParser();
+ } else {
+ $parser = MediaWikiServices::getInstance()->getParserFactory()->create();
+ $parser->startExternalParse( null, ParserOptions::newFromAnon(), Parser::OT_HTML );
+ }
+ $codeBlock = $callFunction( $parser, 'formatCode', [ $codeBlock ] );
+ $additionalOutput = $callFunction( $parser, 'additionalOutput' );
+ }
+
+ return $codeBlock . $actions . $additionalOutput;
}
class ContentHandler extends TextContentHandler {
@@ -118,7 +138,6 @@ class ContentHandler extends TextContentHandler {
$lang = [
'pygmentsLexer' => 'text',
'actions' => [],
- 'linkifiers' => [],
];
}
$out .= renderCode( $content->getText(), $lang, $output );
diff --git a/README.md b/README.md
index 1486f54..fbb4cf7 100644
--- a/README.md
+++ b/README.md
@@ -9,13 +9,14 @@ to provide the following (all in a configurable manner):
* code actions
e.g. automatically link the [WDQS] for SPARQL code blocks[^1]
-* code linkification
- e.g. automatically link Wikidata identifiers in code blocks
-
* code pages
e.g. automatically higlight pages with names ending in `.rq`
as SPARQL (and also display the code actions for them)
+* customizable code display via Lua/[Scribunto]
+ e.g. automatically link Wikidata identifiers in code blocks
+
+
## Example configuration
```php
@@ -28,13 +29,44 @@ $wgCode_languages[] = [
'run' => 'https://query.wikidata.org/#$code',
'embed' => 'https://query.wikidata.org/embed.html#$code',
],
- 'linkifiers' => [
- '/\\b[QP][0-9]+\\b/' => 'https://www.wikidata.org/entity/$1',
- ],
'suffix' => '.rq',
];
```
+## Customizable code display
+
+The display of code blocks can be customized via Lua/[Scribunto]. For example
+if you specify e.g. `"scribuntoModule" => "QueryCode"` for a language then this
+extension will additionally invoke the `Module:QueryCode` Scribunto module for
+every code tag and code page. Such a module could look as follows:
+
+```lua
+local p = {}
+
+p.formatCode = function(frame)
+ local code, tag, is_code_page = frame.args[1], frame.args[2], frame.args[3]
+ local formattedCode = frame.args[4]
+ formattedCode = formattedCode:gsub('[QP][0-9]+', function(m)
+ local a = mw.html.create('a')
+ a:attr('href', 'https://www.wikidata.org/entity/' .. m)
+ a:wikitext(m)
+ return tostring(a)
+ end)
+ return formattedCode;
+end
+
+p.additionalOutput = function(frame)
+ local code, tag, is_code_page = frame.args[1], frame.args[2], frame.args[3]
+ -- HTML returned here is displayed after the code action links
+end
+
+return p
+```
+
+Note that the returned strings are not parsed as Wikitext they must already be
+HTML; any dangerous tags and attributes are removed via MediaWiki's builtin
+`Sanitizer` class.
+
## Linking code actions
Code actions can be linked from other pages via the
@@ -57,4 +89,5 @@ this bears the problem that `|` has to be escaped as `{{!}}`, which can
be quite annoying for languages like SPARQL that use `|` as an operator.
[SyntaxHighlight]: https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:SyntaxHighlight
+[Scribunto]: https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:Scribunto
[WDQS]: https://query.wikidata.org/
diff --git a/examples/languages.php b/examples/languages.php
index 3710f86..6fc4317 100644
--- a/examples/languages.php
+++ b/examples/languages.php
@@ -5,8 +5,5 @@ $wgCode_languages[] = [
'run' => 'https://query.wikidata.org/#$code',
'embed' => 'https://query.wikidata.org/embed.html#$code',
],
- 'linkifiers' => [
- '/\\b[QP][0-9]+\\b/' => 'https://www.wikidata.org/entity/$1',
- ],
'suffix' => '.rq',
];
diff --git a/extension.json b/extension.json
index cfa2c2b..d1e3429 100644
--- a/extension.json
+++ b/extension.json
@@ -6,7 +6,7 @@
"author": "[https://push-f.com/ Martin Fischer]",
"url": "https://www.mediawiki.org/wiki/Extension:Code",
"version": "0.1.0",
- "description": "Provides code pages, code actions and code linkification.",
+ "description": "Provides code pages, code actions and customizable code rendering.",
"config_prefix": "wgCode_",
"config": {
"namespacesWithCodePages": {