mirror of
https://github.com/diocloid/LinkTitles.git
synced 2025-07-13 01:39:30 +02:00
Add Delimiters class.
This commit is contained in:
@ -35,6 +35,7 @@
|
|||||||
"AutoloadClasses": {
|
"AutoloadClasses": {
|
||||||
"LinkTitles\\Extension": "includes/Extension.php",
|
"LinkTitles\\Extension": "includes/Extension.php",
|
||||||
"LinkTitles\\Targets": "includes/Targets.php",
|
"LinkTitles\\Targets": "includes/Targets.php",
|
||||||
|
"LinkTitles\\Delimiters": "includes/Delimiters.php",
|
||||||
"LinkTitles\\Config": "includes/Config.php",
|
"LinkTitles\\Config": "includes/Config.php",
|
||||||
"LinkTitles\\Special": "includes/Special.php",
|
"LinkTitles\\Special": "includes/Special.php",
|
||||||
"LinkTitles\\TestCase": "tests/phpunit/TestCase.php"
|
"LinkTitles\\TestCase": "tests/phpunit/TestCase.php"
|
||||||
@ -64,7 +65,6 @@
|
|||||||
"LinkTitles\\Extension::onParserFirstCallInit"
|
"LinkTitles\\Extension::onParserFirstCallInit"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"callback": "LinkTitles\\Extension::setup",
|
|
||||||
"ExtensionMessagesFiles": {
|
"ExtensionMessagesFiles": {
|
||||||
"LinkTitlesMagic": "includes/Magic.php"
|
"LinkTitlesMagic": "includes/Magic.php"
|
||||||
},
|
},
|
||||||
|
@ -96,6 +96,43 @@ class Config {
|
|||||||
*/
|
*/
|
||||||
public $capitalLinks;
|
public $capitalLinks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not to link to pages only if the page title appears at the
|
||||||
|
* start of a word on the target page (i.e., link 'MediaWiki' to a page
|
||||||
|
* 'Media', but not to a page 'Wiki').
|
||||||
|
*
|
||||||
|
* Set both $wordStartOnly and $wordEndOnly to true to enforce matching
|
||||||
|
* whole titles.
|
||||||
|
*
|
||||||
|
* @var bool $wordStartOnly;
|
||||||
|
*/
|
||||||
|
public $wordStartOnly;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not to link to pages only if the page title appears at the
|
||||||
|
* end of a word on the target page (i.e., link 'MediaWiki' to a page
|
||||||
|
* 'Wiki', but not to a page 'Media').
|
||||||
|
*
|
||||||
|
* Set both $wordStartOnly and $wordEndOnly to true to enforce matching
|
||||||
|
* whole titles.
|
||||||
|
*
|
||||||
|
* @var bool $wordEndOnly;
|
||||||
|
*/
|
||||||
|
public $wordEndOnly;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not to skip templates. If set to true, text inside transclusions
|
||||||
|
* will not be linked.
|
||||||
|
* @var bool $skipTemplates
|
||||||
|
*/
|
||||||
|
public $skipTemplates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not to parse headings.
|
||||||
|
* @var bool $parseHeadings
|
||||||
|
*/
|
||||||
|
public $parseHeadings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new Config object.
|
* Constructs a new Config object.
|
||||||
*
|
*
|
||||||
@ -112,6 +149,10 @@ class Config {
|
|||||||
global $wgLinkTitlesFirstOnly;
|
global $wgLinkTitlesFirstOnly;
|
||||||
global $wgLinkTitlesSmartMode;
|
global $wgLinkTitlesSmartMode;
|
||||||
global $wgCapitalLinks;
|
global $wgCapitalLinks;
|
||||||
|
global $wgLinkTitlesWordStartOnly;
|
||||||
|
global $wgLinkTitlesWordEndOnly;
|
||||||
|
global $wgLinkTitlesSkipTemplates;
|
||||||
|
global $wgLinkTitlesParseHeadings;
|
||||||
$this->parseOnEdit = $wgLinkTitlesParseOnEdit;
|
$this->parseOnEdit = $wgLinkTitlesParseOnEdit;
|
||||||
$this->parseOnRender = $wgLinkTitlesParseOnRender;
|
$this->parseOnRender = $wgLinkTitlesParseOnRender;
|
||||||
$this->preferShortTitles = $wgLinkTitlesPreferShortTitles;
|
$this->preferShortTitles = $wgLinkTitlesPreferShortTitles;
|
||||||
@ -121,6 +162,10 @@ class Config {
|
|||||||
$this->firstOnly = $wgLinkTitlesFirstOnly;
|
$this->firstOnly = $wgLinkTitlesFirstOnly;
|
||||||
$this->smartMode = $wgLinkTitlesSmartMode;
|
$this->smartMode = $wgLinkTitlesSmartMode;
|
||||||
$this->capitalLinks = $wgCapitalLinks; // MediaWiki global variable
|
$this->capitalLinks = $wgCapitalLinks; // MediaWiki global variable
|
||||||
|
$this->wordStartOnly = $wgLinkTitlesWordStartOnly;
|
||||||
|
$this->wordEndOnly = $wgLinkTitlesWordEndOnly;
|
||||||
|
$this->skipTemplates = $wgLinkTitlesSkipTemplates;
|
||||||
|
$this->parseHeadings = $wgLinkTitlesParseHeadings;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
138
includes/Delimiters.php
Normal file
138
includes/Delimiters.php
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The Delimiters class caches a regular expression that delimits text to be parsed.
|
||||||
|
*
|
||||||
|
* Copyright 2012-2017 Daniel Kraus <bovender@bovender.de> ('bovender')
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @author Daniel Kraus <bovender@bovender.de>
|
||||||
|
*/
|
||||||
|
namespace LinkTitles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caches a regular expression that delimits text to be parsed.
|
||||||
|
*/
|
||||||
|
class Delimiters {
|
||||||
|
private static $instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton factory.
|
||||||
|
*
|
||||||
|
* @param Config $config LinkTitles configuration.
|
||||||
|
*/
|
||||||
|
public static function default( Config $config ) {
|
||||||
|
if ( self::$instance === null ) {
|
||||||
|
self::$instance = new Delimiters( $config );
|
||||||
|
}
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates the singleton instance.
|
||||||
|
*
|
||||||
|
* Used for unit testing.
|
||||||
|
*/
|
||||||
|
public static function invalidate() {
|
||||||
|
self::$instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function __construct( Config $config) {
|
||||||
|
$this->config = $config;
|
||||||
|
$this->buildDelimiters();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The splitting expression that separates text to be parsed from text that
|
||||||
|
* must not be parsed.
|
||||||
|
* @var String $splitter
|
||||||
|
*/
|
||||||
|
public $splitter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regex that matches the start of a word; this expression depends on the
|
||||||
|
* setting of LinkTitles\Config->wordStartOnly;
|
||||||
|
* @var String $wordStart
|
||||||
|
*/
|
||||||
|
public $wordStart;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regex that matches the end of a word; this expression depends on the
|
||||||
|
* setting of LinkTitles\Config->wordEndOnly;
|
||||||
|
* @var String $wordEnd
|
||||||
|
*/
|
||||||
|
public $wordEnd;
|
||||||
|
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Builds the delimiter that is used in a regexp to separate
|
||||||
|
* text that should be parsed from text that should not be
|
||||||
|
* parsed (e.g. inside existing links etc.)
|
||||||
|
*/
|
||||||
|
private function buildDelimiters() {
|
||||||
|
// Use unicode character properties rather than \b escape sequences
|
||||||
|
// to detect whole words containing non-ASCII characters as well.
|
||||||
|
// Note that this requires a PCRE library that was compiled with
|
||||||
|
// --enable-unicode-properties
|
||||||
|
( $this->config->wordStartOnly ) ? $this->wordStart = '(?<!\pL)' : $this->wordStart = '';
|
||||||
|
( $this->config->wordEndOnly ) ? $this->wordEnd = '(?!\pL)' : $this->wordEnd = '';
|
||||||
|
|
||||||
|
if ( $this->config->skipTemplates )
|
||||||
|
{
|
||||||
|
// Use recursive regex to balance curly braces;
|
||||||
|
// see http://www.regular-expressions.info/recurse.html
|
||||||
|
$templatesDelimiter = '{{(?>[^{}]|(?R))*}}|';
|
||||||
|
} else {
|
||||||
|
// Match template names (ignoring any piped [[]] links in them)
|
||||||
|
// along with the trailing pipe and parameter name or closing
|
||||||
|
// braces; also match sequences of '|wordcharacters=' (without
|
||||||
|
// spaces in them) that usually only occur as parameter names in
|
||||||
|
// transclusions (but could also occur as wiki table cell contents).
|
||||||
|
// TODO: Find a way to match parameter names in transclusions, but
|
||||||
|
// not in table cells or other sequences involving a pipe character
|
||||||
|
// and equal sign.
|
||||||
|
$templatesDelimiter = '{{[^|]*?(?:(?:\[\[[^]]+]])?)[^|]*?(?:\|(?:\w+=)?|(?:}}))|\|\w+=|';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build a regular expression that will capture existing wiki links ("[[...]]"),
|
||||||
|
// wiki headings ("= ... =", "== ... ==" etc.),
|
||||||
|
// urls ("http://example.com", "[http://example.com]", "[http://example.com Description]",
|
||||||
|
// and email addresses ("mail@example.com").
|
||||||
|
// Since there is a user option to skip headings, we make this part of the expression
|
||||||
|
// optional. Note that in order to use preg_split(), it is important to have only one
|
||||||
|
// capturing subpattern (which precludes the use of conditional subpatterns).
|
||||||
|
( $this->config->parseHeadings ) ? $delimiter = '' : $delimiter = '=+.+?=+|';
|
||||||
|
$urlPattern = '[a-z]+?\:\/\/(?:\S+\.)+\S+(?:\/.*)?';
|
||||||
|
$this->splitter = '/(' . // exclude from linking:
|
||||||
|
'\[\[.*?\]\]|' . // links
|
||||||
|
$delimiter . // titles (if requested)
|
||||||
|
$templatesDelimiter . // templates (if requested)
|
||||||
|
'^ .+?\n|\n .+?\n|\n .+?$|^ .+?$|' . // preformatted text
|
||||||
|
'<nowiki>.*?<.nowiki>|<code>.*?<\/code>|' . // nowiki/code
|
||||||
|
'<pre>.*?<\/pre>|<html>.*?<\/html>|' . // pre/html
|
||||||
|
'<script>.*?<\/script>|' . // script
|
||||||
|
'<gallery>.*?<\/gallery>|' . // gallery
|
||||||
|
'<div.+?>|<\/div>|' . // attributes of div elements
|
||||||
|
'<span.+?>|<\/span>|' . // attributes of span elements
|
||||||
|
'<file>[^<]*<\/file>|' . // stuff inside file elements
|
||||||
|
'style=".+?"|class=".+?"|' . // styles and classes (e.g. of wikitables)
|
||||||
|
'<noautolinks>.*?<\/noautolinks>|' . // custom tag 'noautolinks'
|
||||||
|
'\[' . $urlPattern . '\s.+?\]|'. $urlPattern . '(?=\s|$)|' . // urls
|
||||||
|
'(?<=\b)\S+\@(?:\S+\.)+\S+(?=\b)' . // email addresses
|
||||||
|
')/ismS';
|
||||||
|
}
|
||||||
|
}
|
@ -45,22 +45,9 @@ class Extension {
|
|||||||
/// as a string.
|
/// as a string.
|
||||||
private static $targetTitleText;
|
private static $targetTitleText;
|
||||||
|
|
||||||
/// Delimiter used in a regexp split operation to seperate those parts
|
|
||||||
/// of the page that should be parsed from those that should not be
|
|
||||||
/// parsed (e.g. inside pre-existing links etc.).
|
|
||||||
private static $delimiter;
|
|
||||||
|
|
||||||
private static $wordStartDelim;
|
|
||||||
private static $wordEndDelim;
|
|
||||||
|
|
||||||
public static $ltConsoleOutput;
|
public static $ltConsoleOutput;
|
||||||
public static $ltConsoleOutputDebug;
|
public static $ltConsoleOutputDebug;
|
||||||
|
|
||||||
/// Setup method
|
|
||||||
public static function setup() {
|
|
||||||
self::BuildDelimiters();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Event handler that is hooked to the PageContentSave event.
|
/// Event handler that is hooked to the PageContentSave event.
|
||||||
public static function onPageContentSave( &$wikiPage, &$user, &$content, &$summary,
|
public static function onPageContentSave( &$wikiPage, &$user, &$content, &$summary,
|
||||||
$isMinor, $isWatch, $section, &$flags, &$status ) {
|
$isMinor, $isWatch, $section, &$flags, &$status ) {
|
||||||
@ -120,7 +107,9 @@ class Extension {
|
|||||||
self::$currentTitle = $title;
|
self::$currentTitle = $title;
|
||||||
$newText = $text;
|
$newText = $text;
|
||||||
|
|
||||||
$targets = Targets::default( $title, new Config() );
|
$config = new Config();
|
||||||
|
$delimiters = Delimiters::default( $config );
|
||||||
|
$targets = Targets::default( $title, $config );
|
||||||
|
|
||||||
// Iterate through the page titles
|
// Iterate through the page titles
|
||||||
foreach( $targets->queryResult as $row ) {
|
foreach( $targets->queryResult as $row ) {
|
||||||
@ -132,7 +121,7 @@ class Extension {
|
|||||||
// split the page content by [[...]] groups
|
// split the page content by [[...]] groups
|
||||||
// credits to inhan @ StackOverflow for suggesting preg_split
|
// credits to inhan @ StackOverflow for suggesting preg_split
|
||||||
// see http://stackoverflow.com/questions/10672286
|
// see http://stackoverflow.com/questions/10672286
|
||||||
$arr = preg_split( self::$delimiter, $newText, -1, PREG_SPLIT_DELIM_CAPTURE );
|
$arr = preg_split( $delimiters->splitter, $newText, -1, PREG_SPLIT_DELIM_CAPTURE );
|
||||||
|
|
||||||
// Escape certain special characters in the page title to prevent
|
// Escape certain special characters in the page title to prevent
|
||||||
// regexp compilation errors
|
// regexp compilation errors
|
||||||
@ -146,20 +135,19 @@ class Extension {
|
|||||||
// the title has to be searched for either in a strictly case-sensitive
|
// the title has to be searched for either in a strictly case-sensitive
|
||||||
// way, or in a 'fuzzy' way where the first letter of the title may
|
// way, or in a 'fuzzy' way where the first letter of the title may
|
||||||
// be either case.
|
// be either case.
|
||||||
if ( $wgCapitalLinks && ( $quotedTitle[0] != '\\' )) {
|
if ( $config->capitalLinks && ( $quotedTitle[0] != '\\' )) {
|
||||||
$searchTerm = '((?i)' . $quotedTitle[0] . '(?-i)' .
|
$searchTerm = '((?i)' . $quotedTitle[0] . '(?-i)' .
|
||||||
substr($quotedTitle, 1) . ')';
|
substr($quotedTitle, 1) . ')';
|
||||||
} else {
|
} else {
|
||||||
$searchTerm = '(' . $quotedTitle . ')';
|
$searchTerm = '(' . $quotedTitle . ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
$regex = '/(?<![\:\.\@\/\?\&])' . self::$wordStartDelim .
|
$regex = '/(?<![\:\.\@\/\?\&])' . $delimiters->wordStart . $searchTerm . $delimiters->wordEnd . '/S';
|
||||||
$searchTerm . self::$wordEndDelim . '/S';
|
|
||||||
for ( $i = 0; $i < count( $arr ); $i+=2 ) {
|
for ( $i = 0; $i < count( $arr ); $i+=2 ) {
|
||||||
// even indexes will point to text that is not enclosed by brackets
|
// even indexes will point to text that is not enclosed by brackets
|
||||||
$arr[$i] = preg_replace_callback( $regex,
|
$arr[$i] = preg_replace_callback( $regex,
|
||||||
'LinkTitles\Extension::simpleModeCallback', $arr[$i], $limit, $count );
|
'LinkTitles\Extension::simpleModeCallback', $arr[$i], $limit, $count );
|
||||||
if ( $wgLinkTitlesFirstOnly && ( $count > 0 ) ) {
|
if ( $config->firstOnly && ( $count > 0 ) ) {
|
||||||
$limitReached = true;
|
$limitReached = true;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
@ -169,16 +157,16 @@ class Extension {
|
|||||||
// If smart mode is turned on, the extension will perform a second
|
// If smart mode is turned on, the extension will perform a second
|
||||||
// pass on the page and add links with aliases where the case does
|
// pass on the page and add links with aliases where the case does
|
||||||
// not match.
|
// not match.
|
||||||
if ( $wgLinkTitlesSmartMode && !$limitReached ) {
|
if ( $config->smartMode && !$limitReached ) {
|
||||||
$arr = preg_split( self::$delimiter, $newText, -1, PREG_SPLIT_DELIM_CAPTURE );
|
$arr = preg_split( $delimiters->splitter, $newText, -1, PREG_SPLIT_DELIM_CAPTURE );
|
||||||
|
|
||||||
for ( $i = 0; $i < count( $arr ); $i+=2 ) {
|
for ( $i = 0; $i < count( $arr ); $i+=2 ) {
|
||||||
// even indexes will point to text that is not enclosed by brackets
|
// even indexes will point to text that is not enclosed by brackets
|
||||||
$arr[$i] = preg_replace_callback( '/(?<![\:\.\@\/\?\&])' .
|
$arr[$i] = preg_replace_callback( '/(?<![\:\.\@\/\?\&])' .
|
||||||
self::$wordStartDelim . '(' . $quotedTitle . ')' .
|
$delimiters->wordStart . '(' . $quotedTitle . ')' .
|
||||||
self::$wordEndDelim . '/iS', 'LinkTitles\Extension::smartModeCallback',
|
$delimiters->wordEnd . '/iS', 'LinkTitles\Extension::smartModeCallback',
|
||||||
$arr[$i], $limit, $count );
|
$arr[$i], $limit, $count );
|
||||||
if ( $wgLinkTitlesFirstOnly && ( $count > 0 )) {
|
if ( $config->firstOnly && ( $count > 0 )) {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -368,68 +356,6 @@ class Extension {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the delimiter that is used in a regexp to separate
|
|
||||||
/// text that should be parsed from text that should not be
|
|
||||||
/// parsed (e.g. inside existing links etc.)
|
|
||||||
private static function BuildDelimiters() {
|
|
||||||
// Configuration variables need to be defined here as globals.
|
|
||||||
global $wgLinkTitlesParseHeadings;
|
|
||||||
global $wgLinkTitlesSkipTemplates;
|
|
||||||
global $wgLinkTitlesWordStartOnly;
|
|
||||||
global $wgLinkTitlesWordEndOnly;
|
|
||||||
|
|
||||||
// Use unicode character properties rather than \b escape sequences
|
|
||||||
// to detect whole words containing non-ASCII characters as well.
|
|
||||||
// Note that this requires a PCRE library that was compiled with
|
|
||||||
// --enable-unicode-properties
|
|
||||||
( $wgLinkTitlesWordStartOnly ) ? self::$wordStartDelim = '(?<!\pL)' : self::$wordStartDelim = '';
|
|
||||||
( $wgLinkTitlesWordEndOnly ) ? self::$wordEndDelim = '(?!\pL)' : self::$wordEndDelim = '';
|
|
||||||
|
|
||||||
if ( $wgLinkTitlesSkipTemplates )
|
|
||||||
{
|
|
||||||
// Use recursive regex to balance curly braces;
|
|
||||||
// see http://www.regular-expressions.info/recurse.html
|
|
||||||
$templatesDelimiter = '{{(?>[^{}]|(?R))*}}|';
|
|
||||||
} else {
|
|
||||||
// Match template names (ignoring any piped [[]] links in them)
|
|
||||||
// along with the trailing pipe and parameter name or closing
|
|
||||||
// braces; also match sequences of '|wordcharacters=' (without
|
|
||||||
// spaces in them) that usually only occur as parameter names in
|
|
||||||
// transclusions (but could also occur as wiki table cell contents).
|
|
||||||
// TODO: Find a way to match parameter names in transclusions, but
|
|
||||||
// not in table cells or other sequences involving a pipe character
|
|
||||||
// and equal sign.
|
|
||||||
$templatesDelimiter = '{{[^|]*?(?:(?:\[\[[^]]+]])?)[^|]*?(?:\|(?:\w+=)?|(?:}}))|\|\w+=|';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build a regular expression that will capture existing wiki links ("[[...]]"),
|
|
||||||
// wiki headings ("= ... =", "== ... ==" etc.),
|
|
||||||
// urls ("http://example.com", "[http://example.com]", "[http://example.com Description]",
|
|
||||||
// and email addresses ("mail@example.com").
|
|
||||||
// Since there is a user option to skip headings, we make this part of the expression
|
|
||||||
// optional. Note that in order to use preg_split(), it is important to have only one
|
|
||||||
// capturing subpattern (which precludes the use of conditional subpatterns).
|
|
||||||
( $wgLinkTitlesParseHeadings ) ? $delimiter = '' : $delimiter = '=+.+?=+|';
|
|
||||||
$urlPattern = '[a-z]+?\:\/\/(?:\S+\.)+\S+(?:\/.*)?';
|
|
||||||
self::$delimiter = '/(' . // exclude from linking:
|
|
||||||
'\[\[.*?\]\]|' . // links
|
|
||||||
$delimiter . // titles (if requested)
|
|
||||||
$templatesDelimiter . // templates (if requested)
|
|
||||||
'^ .+?\n|\n .+?\n|\n .+?$|^ .+?$|' . // preformatted text
|
|
||||||
'<nowiki>.*?<.nowiki>|<code>.*?<\/code>|' . // nowiki/code
|
|
||||||
'<pre>.*?<\/pre>|<html>.*?<\/html>|' . // pre/html
|
|
||||||
'<script>.*?<\/script>|' . // script
|
|
||||||
'<gallery>.*?<\/gallery>|' . // gallery
|
|
||||||
'<div.+?>|<\/div>|' . // attributes of div elements
|
|
||||||
'<span.+?>|<\/span>|' . // attributes of span elements
|
|
||||||
'<file>[^<]*<\/file>|' . // stuff inside file elements
|
|
||||||
'style=".+?"|class=".+?"|' . // styles and classes (e.g. of wikitables)
|
|
||||||
'<noautolinks>.*?<\/noautolinks>|' . // custom tag 'noautolinks'
|
|
||||||
'\[' . $urlPattern . '\s.+?\]|'. $urlPattern . '(?=\s|$)|' . // urls
|
|
||||||
'(?<=\b)\S+\@(?:\S+\.)+\S+(?=\b)' . // email addresses
|
|
||||||
')/ismS';
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Local Debugging output function which can send output to console as well
|
/// Local Debugging output function which can send output to console as well
|
||||||
public static function ltDebugLog($text) {
|
public static function ltDebugLog($text) {
|
||||||
if ( self::$ltConsoleOutputDebug ) {
|
if ( self::$ltConsoleOutputDebug ) {
|
||||||
|
42
tests/phpunit/DelimitersTest.php
Normal file
42
tests/phpunit/DelimitersTest.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @group bovender
|
||||||
|
*/
|
||||||
|
class DelimitersTest extends MediaWikiTestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideStartOnly
|
||||||
|
*/
|
||||||
|
public function testDelimitersWordStartOnly( $enabled, $delimiter ) {
|
||||||
|
$config = new LinkTitles\Config();
|
||||||
|
$config->wordStartOnly = $enabled;
|
||||||
|
LinkTitles\Delimiters::invalidate();
|
||||||
|
$d = LinkTitles\Delimiters::default( $config );
|
||||||
|
$this->assertSame( $delimiter, $d->wordStart );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function provideStartOnly() {
|
||||||
|
return [
|
||||||
|
[ true, '(?<!\pL)' ],
|
||||||
|
[ false, '' ]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideEndOnly
|
||||||
|
*/
|
||||||
|
public function testDelimitersWordEndOnly( $enabled, $delimiter ) {
|
||||||
|
$config = new LinkTitles\Config();
|
||||||
|
$config->wordEndOnly = $enabled;
|
||||||
|
LinkTitles\Delimiters::invalidate();
|
||||||
|
$d = LinkTitles\Delimiters::default( $config );
|
||||||
|
$this->assertSame( $delimiter, $d->wordEnd );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function provideEndOnly() {
|
||||||
|
return [
|
||||||
|
[ true, '(?!\pL)' ],
|
||||||
|
[ false, '' ]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user