User:Lord Farin/Long-Term Projects/Extension

From ProofWiki
Jump to navigation Jump to search


On this page I will describe the ideas I have pertaining an extension of PW which will allow for more consistent style, easier transclusions and general ease of use. To this end, I seek to develop (together with Joe) a set of custom tags, maybe namespaces and templates to accommodate for this.

Of course, for this project to be viable, documentation needs to be extensive, and Help:Editing will need serious expansion/adaptation.

Feel free to comment and/or contribute ideas/prototypes.

Progress/Overview of Ideas

Rigour in Page Style

In order to achieve maximal consistency, it will be a good idea to add tags like:


Maybe more can be thought of. These will go with possible HTML attributes (and default values, of course); for example:

title="Section Title"
sectionname="For transclusion reference; eg. 'proof1'"

Furthermore, ideally users could set preferences (like 'by default, expand all folded sections').

This basically comes down to a DOM structure.


Approach Overview

The general idea is as follows:

  • A template {{transclusion}} producing standard transclusion bracketed by:
  • A tag <transclude> which 'flips a switch' in the processing of the tags presented in the page rigour section above.
  • This switch then ensures that the header levels are changed as desired.

Detailed Discussion and Updates

My currently most viable idea to achieve rigour in transclusions is the introduction of the tag or parser function

<transclusion section="section to be transcluded">Title of page whose section must be transcluded</transclusion>
{{#transclusion:Page Title|section=section}}

It will be endowed with further attributes as deemed necessary/possible.

I strive for the possibility to adjust the heading level of all stuff inside the transcluded tag automatically, avoiding the struggle now often encountered.

A snippet of PHP that increments all headers in the input string $subject by the positive integer $increment:

function fnPWadjustHeadings($subject, $increment){
  //Some input checking might be necessary, I skip it for now

  if($increment <= 0){
    return $subject;

  $eq = "";
  $i = 0;
  while($i < $increment){
    $eq .= "=";

  $result = preg_replace('#={2,}#', '$1'.$eq, $subject);

  return $result;

Unfortunately, parser functions do not naturally support named parameters. However, it is possible to work around this, as I have found out. Compare the {{#switch}} function; fortunately, after the first parameter (the page name), only named parameters will be necessary. This means I can build a lot of the code on the implementation of that function.

It appears that parser functions really should be time-invariant constructs, according to MediaWiki documentation (in particular, the paragraph directly after the numbered list at the top of the page). However, I will exploit the 'usually' as a justification to go off the standard path.

The attack plan has changed a little; I will now simply use the template {{transclusion}} with appropriate options, and restricted editing. This will subsequently add some XML tags around the transcluded parts. A custom hook will then be invoked to process the page, removing the tags and applying the desired operations to what is inside them.

//Add this line to the extension core function body
$wgHooks['InternalParseBeforeLinks'][] = 'fnPWparseTransclusion';

 *Aim: to do recursive matching inside $text for <transclude opt1="opt1"> and </transclude>
 *Subsequently, to process the stored information, probably using fnPWadjustHeadings
function fnPWparseTransclusion( &$parser, &$text ){
	$reg = '#<transclude(?P<args>[^>]*?)>(?P<subject>((?!(<transclude|</transclude>)).)*?)</transclude>#s';
	//Find the proto-transcluded sections at deepest level and store them in $matches
	preg_match_all($reg, $text, $matches, PREG_SET_ORDER);
	//As long as results are found, we need to process $text further to process possible nesting
		foreach($matches as $section){
			//Process the HTML attributes given with the <transclude> tag
			$attributes = array();
			$args = explode($section['args'], " ");
			foreach($args as $arg){
				if($arg == "") continue;
				//Put the $arg into processable form
				$attribute = explode($arg, "=");
				$value = strtolower(trim($attribute[1]));
				$option = trim($attribute[0], " \"\'\t\n\r\0\x0B");
					//TODO: process the tags which are allowed to occur
			//TODO: process the subject according to the given attributes
		fnPWparseTransclusion($parser, $text);
	return true;

For now, I will spend some time verifying that this regexp string actually catches what I want (all <transclude>section</transclude> at deepest level (no occurrence of this thing in 'section')). The new regexp seems to achieve exactly this.

I have started writing more of the main body class, and it is almost ready for functional implementation. The attributes I want to implement at the moment are:


To prevent issues with the parsing of the page rigour tags as to whether they are transcluded or not, their processing will have to be delayed to a later point of the page parsing process. Then, it is required to use the command $parser->recursiveTagParse to process them. This is a bit of a workaround but it will ensure that the desired functionality can be implemented.

The whole process of parsing the 'transclusion' tags can be done by adding the tag as a tag extension, probably using some sort of flag to indicate processing stage. --Lord_Farin 17:42, 5 March 2012 (EST)


I have been able to produce working code for the 'adjust header' part. As the code is subject to frequent changes, I won't push it to the main wiki until it has been debugged and thoroughly tested. The swift progress is a welcome surprise. --Lord_Farin 18:33, 8 March 2012 (EST)

Good job! I admire your patience with PHP which I have never as yet had the patience or motivation to learn ... --prime mover 02:45, 9 March 2012 (EST)

Thanks. It all started so many years ago; I jumped to PHP when HTML became too weak for my needs. I wouldn't say I'm an expert or my programming is of professional quality. However, it does get things done, and recently my coding style has become better.

More importantly, I have produced the section-wise transclusion method as well. The biggest downside so far is that it requires all of the page to be in 'section' tags (and defn, thm, and so on). I deem it a minor cost, as it will be neater to enforce that anyway. Exception are the category tags, which, when added at the end of the page, are removed explicitly. Mostly, however, I'm in a 'hurray' mood atm. --Lord_Farin 10:18, 9 March 2012 (EST)

Most of the tags have been implemented. I have been confronted with the fact that section transclusion isn't supporting nested sections at the moment. This will be my next point of attention. --Lord_Farin 10:45, 9 March 2012 (EST)

It turned out that the not-supporting of nested tags is a 'bug/feature' of MediaWiki itself. A fix available on the bug reporting site of MediaWiki has been implemented. Furthermore, support for the 'foldable' attribute has been added. At the moment, the possible states are 'not foldable' and 'initially folded' but this can be amended as is required/desired. This concludes implementation of the functionality described above, both the 'transclusion' and 'page rigour' sections. Feel free to share thoughts and suggest further improvements. --Lord_Farin 05:24, 15 March 2012 (EDT)

Example use is primarily located at and From there, more-or-less intelligent creatures (like PW contributors) should be able to craft their own examples. --Lord_Farin 03:36, 19 March 2012 (EDT)
Will add option to suppress the header, to allow for the common case where the header needs to be different from the original one (Proof -> Proof x, etc.). Also, why is nobody trying to break the stuff? Is there not enough documentation? --Lord_Farin 19:46, 23 March 2012 (EDT)
Eeeh, give me a moment! Been sorting out a personnel mgmt crisis most of the day - I'll be back on track presently. --prime mover (talk) 19:53, 21 February 2013 (UTC)
You're grave-digging :). That call is from March 2012. --Lord_Farin (talk) 21:42, 21 February 2013 (UTC)

An update

The approach has been totally reviewed and the implementation has been rebuilt from scratch. This improves clarity, usability and probably performance.

In the new setup, from the above, only <section> and {{transclude}} are retained. It is no longer my intention to enforce the section tags on every page - it should suffice, especially at first, to use them on pages that need section-wise transclusion. This section-wise transclusion will obsolete the ubiquitous onlyinclude and noinclude tags now used on e.g. subpages. Code is currently up for review by Joe, for security, performance and functionality check. I'm confident because my local copy passes at least the tests for the latter two. Fingers crossed :). --Lord_Farin (talk) 22:11, 19 February 2013 (UTC)

My approach to using it will be to see how you use it and copy your techniques. It is improbable that I will go through and immediately update all the existing stuff to use it, but I will probably be happy to use it once I see how it works in practice. --prime mover (talk) 22:52, 19 February 2013 (UTC)
It has gone live. See Definition:Many-to-One Relation and subpages for sample use. One may correctly note that there is ample room for improvement. This will be worked on soon. --Lord_Farin (talk) 17:38, 20 February 2013 (UTC)
Third version up. Contains numerous improvements over the older versions. I know of no open bugs/feature requests at the moment. Will set to writing a manual (or a draft) soon. --Lord_Farin (talk) 17:59, 21 February 2013 (UTC)