2007-06-29 04:33:14 +00:00
|
|
|
<?php
|
2014-06-01 17:50:34 +00:00
|
|
|
/**
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
|
|
*/
|
|
|
|
|
2022-03-13 00:16:29 +00:00
|
|
|
namespace MediaWiki\SyntaxHighlight;
|
|
|
|
|
|
|
|
use Content;
|
|
|
|
use ExtensionRegistry;
|
|
|
|
use FormatJson;
|
|
|
|
use IContextSource;
|
2023-08-14 18:23:40 +00:00
|
|
|
use MediaWiki\Api\Hook\ApiFormatHighlightHook;
|
|
|
|
use MediaWiki\Content\Hook\ContentGetParserOutputHook;
|
|
|
|
use MediaWiki\Hook\ParserFirstCallInitHook;
|
|
|
|
use MediaWiki\Hook\SoftwareInfoHook;
|
2024-01-05 18:29:59 +00:00
|
|
|
use MediaWiki\Html\Html;
|
2019-07-03 13:58:03 +00:00
|
|
|
use MediaWiki\MediaWikiServices;
|
2024-01-05 18:29:59 +00:00
|
|
|
use MediaWiki\Parser\ParserOutput;
|
|
|
|
use MediaWiki\Parser\Sanitizer;
|
|
|
|
use MediaWiki\Status\Status;
|
2023-08-19 04:19:36 +00:00
|
|
|
use MediaWiki\Title\Title;
|
2022-03-13 00:16:29 +00:00
|
|
|
use Parser;
|
|
|
|
use ParserOptions;
|
2023-06-08 11:13:24 +00:00
|
|
|
use RuntimeException;
|
2022-03-13 00:16:29 +00:00
|
|
|
use TextContent;
|
|
|
|
use WANObjectCache;
|
2022-07-22 22:14:03 +00:00
|
|
|
use Wikimedia\Parsoid\DOM\DocumentFragment;
|
|
|
|
use Wikimedia\Parsoid\Ext\ExtensionTagHandler;
|
|
|
|
use Wikimedia\Parsoid\Ext\ParsoidExtensionAPI;
|
|
|
|
|
2023-08-14 18:23:40 +00:00
|
|
|
class SyntaxHighlight extends ExtensionTagHandler implements
|
|
|
|
ParserFirstCallInitHook,
|
|
|
|
ContentGetParserOutputHook,
|
|
|
|
ApiFormatHighlightHook,
|
|
|
|
SoftwareInfoHook
|
|
|
|
{
|
2008-01-11 09:05:18 +00:00
|
|
|
|
2020-12-30 20:29:59 +00:00
|
|
|
/** @var string CSS class for syntax-highlighted code. Public as used by the updateCSS maintenance script. */
|
2020-05-30 00:34:01 +00:00
|
|
|
public const HIGHLIGHT_CSS_CLASS = 'mw-highlight';
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
|
2017-01-23 21:32:32 +00:00
|
|
|
/** @var int Cache version. Increment whenever the HTML changes. */
|
2020-05-30 00:34:01 +00:00
|
|
|
private const CACHE_VERSION = 2;
|
2015-06-23 15:54:19 +00:00
|
|
|
|
2024-01-22 08:41:41 +00:00
|
|
|
/** @var array<string,string> Mapping of MIME-types to lexer names. */
|
2017-06-15 16:16:11 +00:00
|
|
|
private static $mimeLexers = [
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
'text/javascript' => 'javascript',
|
|
|
|
'application/json' => 'javascript',
|
|
|
|
'text/xml' => 'xml',
|
2017-06-15 16:16:11 +00:00
|
|
|
];
|
2007-06-29 04:33:14 +00:00
|
|
|
|
2022-11-02 19:55:20 +00:00
|
|
|
/**
|
|
|
|
* Returns the maximum number of lines that may be selected for highlighting
|
|
|
|
*
|
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
private static function getMaxLines(): int {
|
|
|
|
$config = MediaWikiServices::getInstance()->getMainConfig();
|
|
|
|
return $config->get( 'SyntaxHighlightMaxLines' );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the maximum input size for the highlighter
|
|
|
|
*
|
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
private static function getMaxBytes(): int {
|
|
|
|
$config = MediaWikiServices::getInstance()->getMainConfig();
|
|
|
|
return $config->get( 'SyntaxHighlightMaxBytes' );
|
|
|
|
}
|
|
|
|
|
2015-05-20 21:36:13 +00:00
|
|
|
/**
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
* Get the Pygments lexer name for a particular language.
|
|
|
|
*
|
2024-01-22 08:41:41 +00:00
|
|
|
* @param string|null $lang Language name.
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
* @return string|null Lexer name, or null if no matching lexer.
|
2015-05-20 21:36:13 +00:00
|
|
|
*/
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
private static function getLexer( $lang ) {
|
|
|
|
static $lexers = null;
|
|
|
|
|
2015-06-26 21:39:15 +00:00
|
|
|
if ( $lang === null ) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2024-01-22 08:41:41 +00:00
|
|
|
$lexers ??= Pygmentize::getLexers();
|
2015-05-20 21:36:13 +00:00
|
|
|
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
$lexer = strtolower( $lang );
|
|
|
|
|
2018-07-29 04:29:30 +00:00
|
|
|
if ( isset( $lexers[$lexer] ) ) {
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
return $lexer;
|
2015-05-20 21:36:13 +00:00
|
|
|
}
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
|
2017-05-10 13:32:52 +00:00
|
|
|
$geshi2pygments = SyntaxHighlightGeSHiCompat::getGeSHiToPygmentsMap();
|
|
|
|
|
2015-06-22 20:29:54 +00:00
|
|
|
// Check if this is a GeSHi lexer name for which there exists
|
|
|
|
// a compatible Pygments lexer with a different name.
|
2017-05-10 13:32:52 +00:00
|
|
|
if ( isset( $geshi2pygments[$lexer] ) ) {
|
|
|
|
$lexer = $geshi2pygments[$lexer];
|
2024-01-22 08:41:41 +00:00
|
|
|
if ( isset( $lexers[$lexer] ) ) {
|
2015-06-22 20:29:54 +00:00
|
|
|
return $lexer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
return null;
|
2015-05-20 21:36:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register parser hook
|
|
|
|
*
|
2019-11-15 05:41:31 +00:00
|
|
|
* @param Parser $parser
|
2015-05-20 21:36:13 +00:00
|
|
|
*/
|
2023-08-14 18:23:40 +00:00
|
|
|
public function onParserFirstCallInit( $parser ) {
|
2022-03-13 00:16:29 +00:00
|
|
|
$parser->setHook( 'source', [ self::class, 'parserHookSource' ] );
|
|
|
|
$parser->setHook( 'syntaxhighlight', [ self::class, 'parserHook' ] );
|
2020-01-06 06:22:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parser hook for <source> to add deprecated tracking category
|
|
|
|
*
|
2022-08-21 11:46:17 +00:00
|
|
|
* @param ?string $text
|
2020-01-06 06:22:26 +00:00
|
|
|
* @param array $args
|
|
|
|
* @param Parser $parser
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public static function parserHookSource( $text, $args, $parser ) {
|
|
|
|
$parser->addTrackingCategory( 'syntaxhighlight-source-category' );
|
|
|
|
return self::parserHook( $text, $args, $parser );
|
2015-05-20 21:36:13 +00:00
|
|
|
}
|
|
|
|
|
2007-06-29 04:33:14 +00:00
|
|
|
/**
|
2024-01-22 08:41:41 +00:00
|
|
|
* @return string[]
|
2022-07-22 22:14:03 +00:00
|
|
|
*/
|
|
|
|
private static function getModuleStyles(): array {
|
|
|
|
return [ 'ext.pygments' ];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2007-06-29 04:33:14 +00:00
|
|
|
*
|
|
|
|
* @param string $text
|
|
|
|
* @param array $args
|
2022-07-22 22:14:03 +00:00
|
|
|
* @param ?Parser $parser
|
|
|
|
* @return array
|
2007-06-29 04:33:14 +00:00
|
|
|
*/
|
2022-07-22 22:14:03 +00:00
|
|
|
private static function processContent( string $text, array $args, ?Parser $parser = null ): array {
|
2008-07-11 18:12:48 +00:00
|
|
|
// Don't trim leading spaces away, just the linefeeds
|
2024-01-22 08:35:50 +00:00
|
|
|
$out = rtrim( trim( $text, "\n" ) );
|
2022-07-22 22:14:03 +00:00
|
|
|
$trackingCats = [];
|
2011-09-16 17:52:28 +00:00
|
|
|
|
2015-07-03 13:42:46 +00:00
|
|
|
// Convert deprecated attributes
|
|
|
|
if ( isset( $args['enclose'] ) ) {
|
|
|
|
if ( $args['enclose'] === 'none' ) {
|
|
|
|
$args['inline'] = true;
|
|
|
|
}
|
|
|
|
unset( $args['enclose'] );
|
2022-07-22 22:14:03 +00:00
|
|
|
$trackingCats[] = 'syntaxhighlight-enclose-category';
|
2015-07-03 13:42:46 +00:00
|
|
|
}
|
|
|
|
|
2019-03-11 03:39:36 +00:00
|
|
|
$lexer = $args['lang'] ?? '';
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
|
2021-01-01 17:53:48 +00:00
|
|
|
$result = self::highlight( $out, $lexer, $args, $parser );
|
2015-06-26 21:39:15 +00:00
|
|
|
if ( !$result->isGood() ) {
|
2022-07-22 22:14:03 +00:00
|
|
|
$trackingCats[] = 'syntaxhighlight-error-category';
|
|
|
|
}
|
|
|
|
|
|
|
|
return [ 'html' => $result->getValue(), 'cats' => $trackingCats ];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parser hook for both <source> and <syntaxhighlight> logic
|
|
|
|
*
|
2022-08-21 11:46:17 +00:00
|
|
|
* @param ?string $text
|
2022-07-22 22:14:03 +00:00
|
|
|
* @param array $args
|
|
|
|
* @param Parser $parser
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public static function parserHook( $text, $args, $parser ) {
|
|
|
|
// Replace strip markers (For e.g. {{#tag:syntaxhighlight|<nowiki>...}})
|
2022-08-21 11:46:17 +00:00
|
|
|
$out = $parser->getStripState()->unstripNoWiki( $text ?? '' );
|
2022-07-22 22:14:03 +00:00
|
|
|
|
|
|
|
$result = self::processContent( $out, $args, $parser );
|
|
|
|
foreach ( $result['cats'] as $cat ) {
|
|
|
|
$parser->addTrackingCategory( $cat );
|
2015-06-26 21:39:15 +00:00
|
|
|
}
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
|
|
|
|
// Register CSS
|
2022-07-22 22:14:03 +00:00
|
|
|
$parser->getOutput()->addModuleStyles( self::getModuleStyles() );
|
2023-03-09 12:46:31 +00:00
|
|
|
if ( !empty( $args['linelinks'] ) && ctype_alpha( $args['linelinks'] ) ) {
|
|
|
|
$parser->getOutput()->addModules( [ 'ext.pygments.linenumbers' ] );
|
|
|
|
}
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
|
2022-07-22 22:14:03 +00:00
|
|
|
return $result['html'];
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @inheritDoc */
|
|
|
|
public function sourceToDom(
|
|
|
|
ParsoidExtensionAPI $extApi, string $text, array $extArgs
|
|
|
|
): ?DocumentFragment {
|
|
|
|
$result = self::processContent( $text, $extApi->extArgsToArray( $extArgs ) );
|
|
|
|
|
|
|
|
// FIXME: There is no API method in Parsoid to add tracking categories
|
|
|
|
// So, $result['cats'] is being ignored
|
|
|
|
|
|
|
|
// Register CSS
|
|
|
|
$extApi->addModuleStyles( self::getModuleStyles() );
|
|
|
|
|
|
|
|
return $extApi->htmlToDom( $result['html'] );
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
}
|
|
|
|
|
2020-12-30 20:29:59 +00:00
|
|
|
/**
|
|
|
|
* Unwrap the <div> wrapper of the Pygments output
|
|
|
|
*
|
|
|
|
* @param string $out Output
|
|
|
|
* @return string Unwrapped output
|
|
|
|
*/
|
2021-07-23 22:43:17 +00:00
|
|
|
private static function unwrap( string $out ): string {
|
2020-12-30 20:29:59 +00:00
|
|
|
if ( $out !== '' ) {
|
|
|
|
$m = [];
|
|
|
|
if ( preg_match( '/^<div class="?mw-highlight"?>(.*)<\/div>$/s', trim( $out ), $m ) ) {
|
|
|
|
$out = trim( $m[1] );
|
|
|
|
} else {
|
2023-06-08 11:13:24 +00:00
|
|
|
throw new RuntimeException( 'Unexpected output from Pygments encountered' );
|
2020-12-30 20:29:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return $out;
|
|
|
|
}
|
|
|
|
|
2018-02-22 23:16:51 +00:00
|
|
|
/**
|
|
|
|
* @param string $code
|
2021-01-01 17:53:48 +00:00
|
|
|
* @param bool $isInline
|
2020-02-29 21:17:22 +00:00
|
|
|
* @return string HTML
|
2018-02-22 23:16:51 +00:00
|
|
|
*/
|
2021-01-01 17:53:48 +00:00
|
|
|
private static function plainCodeWrap( $code, $isInline ) {
|
|
|
|
if ( $isInline ) {
|
2018-02-22 23:29:33 +00:00
|
|
|
return htmlspecialchars( $code, ENT_NOQUOTES );
|
2018-02-22 23:16:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return Html::rawElement(
|
|
|
|
'div',
|
|
|
|
[ 'class' => self::HIGHLIGHT_CSS_CLASS ],
|
|
|
|
Html::element( 'pre', [], $code )
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
/**
|
2021-01-01 17:53:48 +00:00
|
|
|
* @param string $code
|
|
|
|
* @param string|null $lang
|
|
|
|
* @param array $args
|
2022-10-09 16:20:27 +00:00
|
|
|
* @param Parser|null $parser Parser, if generating content to be parsed.
|
2021-01-01 17:53:48 +00:00
|
|
|
* @return Status
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
*/
|
2022-10-09 16:20:27 +00:00
|
|
|
private static function highlightInner( $code, $lang = null, $args = [], ?Parser $parser = null ) {
|
2015-06-26 21:39:15 +00:00
|
|
|
$status = new Status;
|
|
|
|
|
|
|
|
$lexer = self::getLexer( $lang );
|
|
|
|
if ( $lexer === null && $lang !== null ) {
|
|
|
|
$status->warning( 'syntaxhighlight-error-unknown-language', $lang );
|
|
|
|
}
|
|
|
|
|
2018-02-22 23:06:58 +00:00
|
|
|
// For empty tag, output nothing instead of empty <pre>.
|
|
|
|
if ( $code === '' ) {
|
2018-02-22 21:19:53 +00:00
|
|
|
$status->value = '';
|
|
|
|
return $status;
|
2009-06-24 05:25:32 +00:00
|
|
|
}
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
|
2018-02-22 23:06:58 +00:00
|
|
|
$length = strlen( $code );
|
2022-11-02 19:55:20 +00:00
|
|
|
if ( strlen( $code ) > self::getMaxBytes() ) {
|
2018-02-22 23:06:58 +00:00
|
|
|
// Disable syntax highlighting
|
|
|
|
$lexer = null;
|
|
|
|
$status->warning(
|
|
|
|
'syntaxhighlight-error-exceeds-size-limit',
|
|
|
|
$length,
|
2022-11-02 19:55:20 +00:00
|
|
|
self::getMaxBytes()
|
2018-02-22 23:06:58 +00:00
|
|
|
);
|
2015-06-22 23:19:25 +00:00
|
|
|
}
|
|
|
|
|
2021-01-01 17:53:48 +00:00
|
|
|
$isInline = isset( $args['inline'] );
|
|
|
|
$showLines = isset( $args['line'] );
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
|
2021-01-01 17:53:48 +00:00
|
|
|
if ( $isInline ) {
|
2018-02-22 23:29:33 +00:00
|
|
|
$code = trim( $code );
|
|
|
|
}
|
|
|
|
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
if ( $lexer === null ) {
|
2018-02-22 23:06:58 +00:00
|
|
|
// When syntax highlighting is disabled..
|
2021-01-01 17:53:48 +00:00
|
|
|
$status->value = self::plainCodeWrap( $code, $isInline );
|
2015-06-26 21:39:15 +00:00
|
|
|
return $status;
|
2009-06-24 05:25:32 +00:00
|
|
|
}
|
2008-09-28 15:30:45 +00:00
|
|
|
|
2022-10-09 16:20:27 +00:00
|
|
|
if ( $parser && !$parser->incrementExpensiveFunctionCount() ) {
|
|
|
|
// Highlighting is expensive, return unstyled
|
|
|
|
$status->value = self::plainCodeWrap( $code, $isInline );
|
|
|
|
return $status;
|
|
|
|
}
|
|
|
|
|
2017-06-15 16:16:11 +00:00
|
|
|
$options = [
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
'cssclass' => self::HIGHLIGHT_CSS_CLASS,
|
|
|
|
'encoding' => 'utf-8',
|
2017-06-15 16:16:11 +00:00
|
|
|
];
|
2008-09-28 15:30:45 +00:00
|
|
|
|
2008-07-11 18:12:48 +00:00
|
|
|
// Line numbers
|
2021-01-01 17:53:48 +00:00
|
|
|
if ( $showLines ) {
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
$options['linenos'] = 'inline';
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( $lexer === 'php' && strpos( $code, '<?php' ) === false ) {
|
|
|
|
$options['startinline'] = 1;
|
2007-06-29 04:33:14 +00:00
|
|
|
}
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
|
|
|
|
// Highlight specific lines
|
2015-05-20 21:36:13 +00:00
|
|
|
if ( isset( $args['highlight'] ) ) {
|
2008-07-10 20:55:02 +00:00
|
|
|
$lines = self::parseHighlightLines( $args['highlight'] );
|
2011-12-02 17:00:19 +00:00
|
|
|
if ( count( $lines ) ) {
|
2015-06-23 13:49:16 +00:00
|
|
|
$options['hl_lines'] = implode( ' ', $lines );
|
2010-08-09 06:56:38 +00:00
|
|
|
}
|
2008-07-10 12:45:20 +00:00
|
|
|
}
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
|
2007-06-29 04:33:14 +00:00
|
|
|
// Starting line number
|
2017-02-21 19:20:16 +00:00
|
|
|
if ( isset( $args['start'] ) && ctype_digit( $args['start'] ) ) {
|
|
|
|
$options['linenostart'] = (int)$args['start'];
|
2010-08-09 06:56:38 +00:00
|
|
|
}
|
2011-11-20 18:07:20 +00:00
|
|
|
|
2021-01-01 19:48:57 +00:00
|
|
|
if ( !empty( $args['linelinks'] ) && ctype_alpha( $args['linelinks'] ) ) {
|
|
|
|
$options['linespans'] = $args['linelinks'];
|
|
|
|
}
|
|
|
|
|
2021-01-01 17:53:48 +00:00
|
|
|
if ( $isInline ) {
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
$options['nowrap'] = 1;
|
|
|
|
}
|
2011-02-10 01:59:14 +00:00
|
|
|
|
2019-07-03 13:58:03 +00:00
|
|
|
$cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
|
2018-02-22 23:29:33 +00:00
|
|
|
$error = null;
|
|
|
|
$output = $cache->getWithSetCallback(
|
|
|
|
$cache->makeGlobalKey( 'highlight', self::makeCacheKeyHash( $code, $lexer, $options ) ),
|
|
|
|
$cache::TTL_MONTH,
|
2021-09-03 02:30:32 +00:00
|
|
|
static function ( $oldValue, &$ttl ) use ( $code, $lexer, $options, &$error ) {
|
|
|
|
try {
|
|
|
|
return Pygmentize::highlight( $lexer, $code, $options );
|
|
|
|
} catch ( PygmentsException $e ) {
|
2018-02-22 23:29:33 +00:00
|
|
|
$ttl = WANObjectCache::TTL_UNCACHEABLE;
|
2021-09-03 02:30:32 +00:00
|
|
|
$error = $e->getMessage();
|
2018-02-22 23:29:33 +00:00
|
|
|
return null;
|
|
|
|
}
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
}
|
2018-02-22 23:29:33 +00:00
|
|
|
);
|
2015-12-02 21:21:11 +00:00
|
|
|
|
2018-02-22 23:29:33 +00:00
|
|
|
if ( $error !== null || $output === null ) {
|
|
|
|
$status->warning( 'syntaxhighlight-error-pygments-invocation-failure' );
|
2019-12-22 06:40:07 +00:00
|
|
|
if ( $error !== null ) {
|
|
|
|
wfWarn( 'Failed to invoke Pygments: ' . $error );
|
|
|
|
} else {
|
|
|
|
wfWarn( 'Invoking Pygments returned blank output with no error response' );
|
|
|
|
}
|
|
|
|
|
2018-02-22 23:29:33 +00:00
|
|
|
// Fall back to preformatted code without syntax highlighting
|
2021-01-01 17:53:48 +00:00
|
|
|
$output = self::plainCodeWrap( $code, $isInline );
|
|
|
|
}
|
|
|
|
|
|
|
|
$status->value = $output;
|
|
|
|
|
|
|
|
return $status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Highlight a code-block using a particular lexer.
|
|
|
|
*
|
|
|
|
* This produces raw HTML (wrapped by Status), the caller is responsible
|
|
|
|
* for making sure the "ext.pygments" module is loaded in the output.
|
|
|
|
*
|
|
|
|
* @param string $code Code to highlight.
|
|
|
|
* @param string|null $lang Language name, or null to use plain markup.
|
|
|
|
* @param array $args Associative array of additional arguments.
|
|
|
|
* If it contains a 'line' key, the output will include line numbers.
|
|
|
|
* If it includes a 'highlight' key, the value will be parsed as a
|
2021-01-01 19:48:57 +00:00
|
|
|
* comma-separated list of lines and line-ranges to highlight.
|
2021-01-01 17:53:48 +00:00
|
|
|
* If it contains a 'start' key, the value will be used as the line at which to
|
2021-01-01 19:48:57 +00:00
|
|
|
* start highlighting.
|
2021-01-01 17:53:48 +00:00
|
|
|
* If it contains a 'inline' key, the output will not be wrapped in `<div><pre/></div>`.
|
2021-01-01 19:48:57 +00:00
|
|
|
* If it contains a 'linelinks' key, lines will have links and anchors with a prefix
|
|
|
|
* of the value. Similar to the lineanchors+linespans features in Pygments.
|
2021-01-01 17:53:48 +00:00
|
|
|
* @param Parser|null $parser Parser, if generating content to be parsed.
|
|
|
|
* @return Status Status object, with HTML representing the highlighted
|
|
|
|
* code as its value.
|
|
|
|
*/
|
|
|
|
public static function highlight( $code, $lang = null, $args = [], ?Parser $parser = null ) {
|
2022-10-09 16:20:27 +00:00
|
|
|
$status = self::highlightInner( $code, $lang, $args, $parser );
|
2021-01-01 17:53:48 +00:00
|
|
|
$output = $status->getValue();
|
|
|
|
|
|
|
|
$isInline = isset( $args['inline'] );
|
|
|
|
$showLines = isset( $args['line'] );
|
|
|
|
$lexer = self::getLexer( $lang );
|
|
|
|
|
|
|
|
// Post-Pygment HTML transformations.
|
|
|
|
|
2021-01-01 19:48:57 +00:00
|
|
|
if ( $showLines ) {
|
|
|
|
$lineReplace = Html::element( 'span', [ 'class' => 'linenos', 'data-line' => '$1' ] );
|
|
|
|
if ( !empty( $args['linelinks'] ) ) {
|
|
|
|
$lineReplace = Html::rawElement(
|
|
|
|
'a',
|
|
|
|
[ 'href' => '#' . $args['linelinks'] . '-$1' ],
|
|
|
|
$lineReplace
|
|
|
|
);
|
|
|
|
}
|
|
|
|
// Convert line numbers to data attributes so they
|
|
|
|
// can be displayed as CSS generated content and be
|
|
|
|
// unselectable in all browsers.
|
|
|
|
$output = preg_replace(
|
|
|
|
'`<span class="linenos">\s*([^<]*)\s*</span>`',
|
|
|
|
$lineReplace,
|
|
|
|
$output
|
|
|
|
);
|
|
|
|
}
|
2021-01-01 17:53:48 +00:00
|
|
|
|
|
|
|
// Allow certain HTML attributes
|
|
|
|
$htmlAttribs = Sanitizer::validateAttributes(
|
|
|
|
$args, array_flip( [ 'style', 'class', 'id' ] )
|
|
|
|
);
|
|
|
|
|
|
|
|
$dir = ( isset( $args['dir'] ) && $args['dir'] === 'rtl' ) ? 'rtl' : 'ltr';
|
|
|
|
|
|
|
|
// Build class list
|
|
|
|
$classList = [];
|
|
|
|
if ( isset( $htmlAttribs['class'] ) ) {
|
|
|
|
$classList[] = $htmlAttribs['class'];
|
|
|
|
}
|
|
|
|
$classList[] = self::HIGHLIGHT_CSS_CLASS;
|
|
|
|
if ( $lexer !== null ) {
|
|
|
|
$classList[] = self::HIGHLIGHT_CSS_CLASS . '-lang-' . $lexer;
|
|
|
|
}
|
2021-01-15 17:29:46 +00:00
|
|
|
$classList[] = 'mw-content-' . $dir;
|
2021-01-01 17:53:48 +00:00
|
|
|
if ( $showLines ) {
|
|
|
|
$classList[] = self::HIGHLIGHT_CSS_CLASS . '-lines';
|
|
|
|
}
|
|
|
|
$htmlAttribs['class'] = implode( ' ', $classList );
|
|
|
|
$htmlAttribs['dir'] = $dir;
|
|
|
|
'@phan-var array{class:string,dir:string} $htmlAttribs';
|
2011-02-10 01:59:14 +00:00
|
|
|
|
2021-01-01 17:53:48 +00:00
|
|
|
if ( $isInline ) {
|
2018-02-22 23:29:33 +00:00
|
|
|
// We've already trimmed the input $code before highlighting,
|
|
|
|
// but pygment's standard out adds a line break afterwards,
|
|
|
|
// which would then be preserved in the paragraph that wraps this,
|
|
|
|
// and become visible as a space. Avoid that.
|
2015-07-03 13:42:46 +00:00
|
|
|
$output = trim( $output );
|
2021-01-01 17:53:48 +00:00
|
|
|
|
|
|
|
// Enforce inlineness. Stray newlines may result in unexpected list and paragraph processing
|
|
|
|
// (also known as doBlockLevels()).
|
|
|
|
$output = str_replace( "\n", ' ', $output );
|
|
|
|
$output = Html::rawElement( 'code', $htmlAttribs, $output );
|
|
|
|
} else {
|
|
|
|
$output = self::unwrap( $output );
|
|
|
|
|
|
|
|
if ( $parser ) {
|
|
|
|
// Use 'nowiki' strip marker to prevent list processing (also known as doBlockLevels()).
|
|
|
|
// However, leave the wrapping <div/> outside to prevent <p/>-wrapping.
|
|
|
|
$marker = $parser::MARKER_PREFIX . '-syntaxhighlightinner-' .
|
|
|
|
sprintf( '%08X', $parser->mMarkerIndex++ ) . $parser::MARKER_SUFFIX;
|
2021-02-19 22:08:41 +00:00
|
|
|
$parser->getStripState()->addNoWiki( $marker, $output );
|
2021-01-01 17:53:48 +00:00
|
|
|
$output = $marker;
|
|
|
|
}
|
|
|
|
|
|
|
|
$output = Html::openElement( 'div', $htmlAttribs ) .
|
|
|
|
$output .
|
|
|
|
Html::closeElement( 'div' );
|
2007-06-29 04:33:14 +00:00
|
|
|
}
|
2011-02-10 01:59:14 +00:00
|
|
|
|
2015-06-26 21:39:15 +00:00
|
|
|
$status->value = $output;
|
|
|
|
return $status;
|
2011-02-10 01:59:14 +00:00
|
|
|
}
|
|
|
|
|
2015-06-23 15:54:19 +00:00
|
|
|
/**
|
|
|
|
* Construct a cache key for the results of a Pygments invocation.
|
|
|
|
*
|
|
|
|
* @param string $code Code to be highlighted.
|
|
|
|
* @param string $lexer Lexer name.
|
|
|
|
* @param array $options Options array.
|
|
|
|
* @return string Cache key.
|
|
|
|
*/
|
2018-02-22 23:29:33 +00:00
|
|
|
private static function makeCacheKeyHash( $code, $lexer, $options ) {
|
2015-06-23 15:54:19 +00:00
|
|
|
$optionString = FormatJson::encode( $options, false, FormatJson::ALL_OK );
|
2018-02-22 23:29:33 +00:00
|
|
|
return md5( "{$code}|{$lexer}|{$optionString}|" . self::CACHE_VERSION );
|
2015-06-23 15:54:19 +00:00
|
|
|
}
|
|
|
|
|
2008-07-10 20:55:02 +00:00
|
|
|
/**
|
|
|
|
* Take an input specifying a list of lines to highlight, returning
|
|
|
|
* a raw list of matching line numbers.
|
|
|
|
*
|
|
|
|
* Input is comma-separated list of lines or line ranges.
|
|
|
|
*
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
* @param string $lineSpec
|
|
|
|
* @return int[] Line numbers.
|
2008-07-10 20:55:02 +00:00
|
|
|
*/
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
protected static function parseHighlightLines( $lineSpec ) {
|
2017-06-15 16:16:11 +00:00
|
|
|
$lines = [];
|
2015-06-23 13:49:16 +00:00
|
|
|
$values = array_map( 'trim', explode( ',', $lineSpec ) );
|
|
|
|
foreach ( $values as $value ) {
|
|
|
|
if ( ctype_digit( $value ) ) {
|
|
|
|
$lines[] = (int)$value;
|
|
|
|
} elseif ( strpos( $value, '-' ) !== false ) {
|
2019-12-22 06:40:07 +00:00
|
|
|
list( $start, $end ) = array_map( 'intval', explode( '-', $value ) );
|
2015-06-23 13:49:16 +00:00
|
|
|
if ( self::validHighlightRange( $start, $end ) ) {
|
2019-12-22 06:40:07 +00:00
|
|
|
for ( $i = $start; $i <= $end; $i++ ) {
|
2015-06-23 13:49:16 +00:00
|
|
|
$lines[] = $i;
|
|
|
|
}
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-02 19:55:20 +00:00
|
|
|
if ( count( $lines ) > self::getMaxLines() ) {
|
|
|
|
$lines = array_slice( $lines, 0, self::getMaxLines() );
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
break;
|
2008-09-28 15:30:45 +00:00
|
|
|
}
|
|
|
|
}
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
return $lines;
|
2008-09-28 15:30:45 +00:00
|
|
|
}
|
|
|
|
|
2015-06-23 13:49:16 +00:00
|
|
|
/**
|
|
|
|
* Validate a provided input range
|
2017-10-07 15:16:00 +00:00
|
|
|
* @param int $start
|
|
|
|
* @param int $end
|
2015-06-23 13:49:16 +00:00
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
protected static function validHighlightRange( $start, $end ) {
|
|
|
|
// Since we're taking this tiny range and producing a an
|
|
|
|
// array of every integer between them, it would be trivial
|
|
|
|
// to DoS the system by asking for a huge range.
|
|
|
|
// Impose an arbitrary limit on the number of lines in a
|
|
|
|
// given range to reduce the impact.
|
2019-12-22 06:40:07 +00:00
|
|
|
return $start > 0 &&
|
2015-06-23 13:49:16 +00:00
|
|
|
$start < $end &&
|
2022-11-02 19:55:20 +00:00
|
|
|
$end - $start < self::getMaxLines();
|
2015-06-23 13:49:16 +00:00
|
|
|
}
|
|
|
|
|
2012-10-16 10:33:26 +00:00
|
|
|
/**
|
|
|
|
* Hook into Content::getParserOutput to provide syntax highlighting for
|
|
|
|
* script content.
|
|
|
|
*
|
2017-10-07 15:16:00 +00:00
|
|
|
* @param Content $content
|
|
|
|
* @param Title $title
|
|
|
|
* @param int $revId
|
|
|
|
* @param ParserOptions $options
|
|
|
|
* @param bool $generateHtml
|
2022-01-11 22:01:22 +00:00
|
|
|
* @param ParserOutput &$parserOutput
|
2012-10-16 10:33:26 +00:00
|
|
|
* @return bool
|
|
|
|
* @since MW 1.21
|
|
|
|
*/
|
2023-08-14 18:23:40 +00:00
|
|
|
public function onContentGetParserOutput( $content, $title,
|
|
|
|
$revId, $options, $generateHtml, &$parserOutput
|
2017-07-08 09:51:33 +00:00
|
|
|
) {
|
2019-10-28 20:13:31 +00:00
|
|
|
global $wgTextModelsToParse;
|
2012-10-16 10:33:26 +00:00
|
|
|
|
2021-05-17 22:34:21 +00:00
|
|
|
// Hope that the "SyntaxHighlightModels" attribute does not contain silly types.
|
|
|
|
if ( !( $content instanceof TextContent ) ) {
|
|
|
|
// Oops! Non-text content? Let MediaWiki handle this.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
if ( !$generateHtml ) {
|
|
|
|
// Nothing special for us to do, let MediaWiki handle this.
|
|
|
|
return true;
|
|
|
|
}
|
2015-05-20 21:36:13 +00:00
|
|
|
|
2021-02-11 01:12:03 +00:00
|
|
|
// Determine the SyntaxHighlight language from the page's
|
|
|
|
// content model. Extensions can extend the default CSS/JS
|
|
|
|
// mapping by setting the SyntaxHighlightModels attribute.
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
$extension = ExtensionRegistry::getInstance();
|
2021-02-11 01:12:03 +00:00
|
|
|
$models = $extension->getAttribute( 'SyntaxHighlightModels' ) + [
|
|
|
|
CONTENT_MODEL_CSS => 'css',
|
|
|
|
CONTENT_MODEL_JAVASCRIPT => 'javascript',
|
|
|
|
];
|
2012-10-16 10:33:26 +00:00
|
|
|
$model = $content->getModel();
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
if ( !isset( $models[$model] ) ) {
|
2012-10-16 10:33:26 +00:00
|
|
|
// We don't care about this model, carry on.
|
|
|
|
return true;
|
|
|
|
}
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
$lexer = $models[$model];
|
2021-05-17 22:34:21 +00:00
|
|
|
$text = $content->getText();
|
2014-07-30 19:09:05 +00:00
|
|
|
|
|
|
|
// Parse using the standard parser to get links etc. into the database, HTML is replaced below.
|
|
|
|
// We could do this using $content->fillParserOutput(), but alas it is 'protected'.
|
2023-06-06 12:35:40 +00:00
|
|
|
if ( in_array( $model, $wgTextModelsToParse, true ) ) {
|
2022-01-11 22:01:22 +00:00
|
|
|
$parserOutput = MediaWikiServices::getInstance()->getParser()
|
2019-10-28 20:13:31 +00:00
|
|
|
->parse( $text, $title, $options, true, true, $revId );
|
2012-10-16 10:33:26 +00:00
|
|
|
}
|
|
|
|
|
2021-01-01 19:48:57 +00:00
|
|
|
$status = self::highlight( $text, $lexer, [ 'line' => true, 'linelinks' => 'L' ] );
|
2015-06-26 21:39:15 +00:00
|
|
|
if ( !$status->isOK() ) {
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
return true;
|
2015-05-20 21:36:13 +00:00
|
|
|
}
|
2015-06-26 21:39:15 +00:00
|
|
|
$out = $status->getValue();
|
2015-05-20 21:36:13 +00:00
|
|
|
|
2022-07-22 22:14:03 +00:00
|
|
|
$parserOutput->addModuleStyles( self::getModuleStyles() );
|
2022-01-11 22:01:22 +00:00
|
|
|
$parserOutput->addModules( [ 'ext.pygments.linenumbers' ] );
|
|
|
|
$parserOutput->setText( $out );
|
2012-10-16 10:33:26 +00:00
|
|
|
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
// Inform MediaWiki that we have parsed this page and it shouldn't mess with it.
|
|
|
|
return false;
|
2014-09-17 19:32:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hook to provide syntax highlighting for API pretty-printed output
|
|
|
|
*
|
|
|
|
* @param IContextSource $context
|
|
|
|
* @param string $text
|
|
|
|
* @param string $mime
|
|
|
|
* @param string $format
|
|
|
|
* @since MW 1.24
|
2017-03-27 23:25:36 +00:00
|
|
|
* @return bool
|
2014-09-17 19:32:35 +00:00
|
|
|
*/
|
2023-08-14 18:23:40 +00:00
|
|
|
public function onApiFormatHighlight( $context, $text, $mime, $format ) {
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
if ( !isset( self::$mimeLexers[$mime] ) ) {
|
|
|
|
return true;
|
2014-09-17 19:32:35 +00:00
|
|
|
}
|
|
|
|
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
$lexer = self::$mimeLexers[$mime];
|
2015-06-26 21:39:15 +00:00
|
|
|
$status = self::highlight( $text, $lexer );
|
|
|
|
if ( !$status->isOK() ) {
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
return true;
|
2012-10-16 10:33:26 +00:00
|
|
|
}
|
|
|
|
|
2015-06-26 21:39:15 +00:00
|
|
|
$out = $status->getValue();
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
if ( preg_match( '/^<pre([^>]*)>/i', $out, $m ) ) {
|
|
|
|
$attrs = Sanitizer::decodeTagAttributes( $m[1] );
|
|
|
|
$attrs['class'] .= ' api-pretty-content';
|
|
|
|
$encodedAttrs = Sanitizer::safeEncodeTagAttributes( $attrs );
|
2018-09-03 19:50:49 +00:00
|
|
|
$out = '<pre' . $encodedAttrs . '>' . substr( $out, strlen( $m[0] ) );
|
2010-08-09 06:56:38 +00:00
|
|
|
}
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
$output = $context->getOutput();
|
2022-07-22 22:14:03 +00:00
|
|
|
$output->addModuleStyles( self::getModuleStyles() );
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
$output->addHTML( '<div dir="ltr">' . $out . '</div>' );
|
2013-02-13 20:15:37 +00:00
|
|
|
|
Highlight using Pygments rather than Geshi
GeSHi is unmaintained, lacks support for many popular modern languages, and
suffers from deep architectural flaws, chief among them the inconsistent
tokenization of different languages, each of which requires a custom
stylesheet.
Pygments is a well-maintained alternative. It is, by my count, the most popular
syntax highlighting library around. It is BSD-licensed, actively maintained,
and is widely used in PHP projects.
To keep this easy to review, this change does not include update for l10n
files, and it does not delete the geshi/ directory. I will do those in a
separate patch.
The chief change between this and the previous implementation is that errors
result in the code block not being highlighted, as opposed to not being printed
at all, having been replaced by an angry red error message. I think that is the
right user experience. If you go to StackOverflow or GitHub and try to mark up
your code block as being written in some language that their highlighter
doesn't know about, you don't get an error message -- the code simply doesn't
get highlighted.
Because we don't recursively load dependencies for extensions, to test this,
you will need to create a composer.local.json in $IP and add:
{
"extra": {
"merge-plugin": {
"include": [
"extensions/SyntaxHighlight_GeSHi/composer.json"
]
}
}
}
Then run `composer update`.
Bug: T85794
Change-Id: I07446ec9893fae3d1e394f435d3d95cf8be6bc33
2015-06-16 03:52:58 +00:00
|
|
|
// Inform MediaWiki that we have parsed this page and it shouldn't mess with it.
|
|
|
|
return false;
|
2014-04-16 20:23:12 +00:00
|
|
|
}
|
2021-09-03 02:35:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Hook to add Pygments version to Special:Version
|
|
|
|
*
|
|
|
|
* @see https://www.mediawiki.org/wiki/Manual:Hooks/SoftwareInfo
|
|
|
|
* @param array &$software
|
|
|
|
*/
|
2023-08-14 18:23:40 +00:00
|
|
|
public function onSoftwareInfo( &$software ) {
|
2021-09-03 02:35:45 +00:00
|
|
|
try {
|
|
|
|
$software['[https://pygments.org/ Pygments]'] = Pygmentize::getVersion();
|
|
|
|
} catch ( PygmentsException $e ) {
|
|
|
|
// pass
|
|
|
|
}
|
|
|
|
}
|
2011-08-14 06:59:35 +00:00
|
|
|
}
|