From f81f4c1fa61775bcbd409c8c4b3a0911904906c2 Mon Sep 17 00:00:00 2001 From: Arash Boostani Date: Tue, 5 May 2009 22:49:45 +0000 Subject: [PATCH] Added an extension, called EditSectionHiliteLink, that highlights the appropriate section when the user mouses over the section edit links. Also, modified the Parser to enclose each section in a div if $wgSectionContainers is set. --- .../EditSectionHiliteLink.css | 5 ++ .../EditSectionHiliteLink.hooks.php | 74 +++++++++++++++++++ .../EditSectionHiliteLink.js | 9 +++ .../EditSectionHiliteLink.php | 57 ++++++++++++++ includes/parser/Parser.php | 57 +++++++++++++- 5 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 extensions/EditSectionHiliteLink/EditSectionHiliteLink.css create mode 100644 extensions/EditSectionHiliteLink/EditSectionHiliteLink.hooks.php create mode 100644 extensions/EditSectionHiliteLink/EditSectionHiliteLink.js create mode 100644 extensions/EditSectionHiliteLink/EditSectionHiliteLink.php diff --git a/extensions/EditSectionHiliteLink/EditSectionHiliteLink.css b/extensions/EditSectionHiliteLink/EditSectionHiliteLink.css new file mode 100644 index 0000000000..0621dde060 --- /dev/null +++ b/extensions/EditSectionHiliteLink/EditSectionHiliteLink.css @@ -0,0 +1,5 @@ +/* CSS StyleSheet for EditSectionHiliteLink extensions */ + +div.edit_section_hilite { + background-color:Lavender; +} \ No newline at end of file diff --git a/extensions/EditSectionHiliteLink/EditSectionHiliteLink.hooks.php b/extensions/EditSectionHiliteLink/EditSectionHiliteLink.hooks.php new file mode 100644 index 0000000000..0d8851cac3 --- /dev/null +++ b/extensions/EditSectionHiliteLink/EditSectionHiliteLink.hooks.php @@ -0,0 +1,74 @@ +addScript( + Xml::element( + 'script', + array( + 'type' => $wgJsMimeType, + 'src' => $wgScriptPath . '/extensions/EditSectionHiliteLink/EditSectionHiliteLink.js?' . + $wgEditSectionHiliteLinkStyleVersion + ), + '', + false + ) + ); + // Continue + return true; + } + + /** + * BeforePageDisplay hook + * Add css style sheet + */ + public static function addCSS( + $out + ) { + global $wgScriptPath, $wgEditSectionHiliteLinkStyleVersion; + // FIXME: assumes standard dir structure + // Add css for various styles + $out->addLink( + array( + 'rel' => 'stylesheet', + 'type' => 'text/css', + 'href' => $wgScriptPath . '/extensions/EditSectionHiliteLink/EditSectionHiliteLink.css?' . + $wgEditSectionHiliteLinkStyleVersion, + ) + ); + // Continue + return true; + } +} diff --git a/extensions/EditSectionHiliteLink/EditSectionHiliteLink.js b/extensions/EditSectionHiliteLink/EditSectionHiliteLink.js new file mode 100644 index 0000000000..acf509bbf6 --- /dev/null +++ b/extensions/EditSectionHiliteLink/EditSectionHiliteLink.js @@ -0,0 +1,9 @@ +/* JavaScript for Drafts extension */ + +function editSectionHiliteOn (sectionID) { + document.getElementById(sectionID).className = 'edit_section_hilite'; +} + +function editSectionHiliteOff (sectionID) { + document.getElementById(sectionID).className = ''; +} \ No newline at end of file diff --git a/extensions/EditSectionHiliteLink/EditSectionHiliteLink.php b/extensions/EditSectionHiliteLink/EditSectionHiliteLink.php new file mode 100644 index 0000000000..8ba3d85a40 --- /dev/null +++ b/extensions/EditSectionHiliteLink/EditSectionHiliteLink.php @@ -0,0 +1,57 @@ + + * @license GPL v2 + * @version 0.1.0 + */ + +// Check environment +if ( !defined( 'MEDIAWIKI' ) ) { + echo( "This is an extension to MediaWiki and cannot be run standalone.\n" ); + die( - 1 ); +} + +/* Configuration */ + +// Credits +$wgExtensionCredits['other'][] = array( + 'path' => __FILE__, + 'name' => 'EditSectionHiliteLink', + 'author' => 'Arash Boostani', + 'url' => 'http://www.mediawiki.org/wiki/Extension:EditSectionHiliteLink', + 'description' => 'Hilight the appropriate section of an article when you mouse over the edit link', + 'description-msg' => 'EditSectionHiliteLink-desc', +); + +// Turn on the section container divs in the Parser +$wgSectionContainers = true; + +// Shortcut to this extension directory +$dir = dirname( __FILE__ ) . '/'; + +# Bump the version number every time you change any of the .css/.js files +$wgEditSectionHiliteLinkStyleVersion = 2; + +$wgAutoloadClasses['EditSectionHiliteLinkHooks'] = $dir . 'EditSectionHiliteLink.hooks.php'; + +// Register edit link interception +$wgHooks['DoEditSectionLink'][] = 'EditSectionHiliteLinkHooks::interceptLink'; + +// Register ajax add script hook +$wgHooks['AjaxAddScript'][] = 'EditSectionHiliteLinkHooks::addJS'; + +// Register css add script hook +$wgHooks['BeforePageDisplay'][] = 'EditSectionHiliteLinkHooks::addCSS'; + +?> \ No newline at end of file diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php index 0f57d571b2..fa0b57d651 100644 --- a/includes/parser/Parser.php +++ b/includes/parser/Parser.php @@ -3371,7 +3371,7 @@ class Parser * @private */ function formatHeadings( $text, $isMain=true ) { - global $wgMaxTocLevel, $wgContLang, $wgEnforceHtmlIds; + global $wgMaxTocLevel, $wgContLang, $wgEnforceHtmlIds, $wgSectionContainers; $doNumberHeadings = $this->mOptions->getNumberHeadings(); $showEditLink = $this->mOptions->getEditSection(); @@ -3658,6 +3658,10 @@ class Parser $blocks = preg_split( '/.*?<\/H[1-6]>/i', $text ); $i = 0; + if ( $wgSectionContainers ) { + $openDivs = array(); + } + foreach( $blocks as $block ) { if( $showEditLink && $headlineCount > 0 && $i == 0 && $block !== "\n" ) { # This is the [edit] link that appears for the top block of text when @@ -3672,6 +3676,34 @@ class Parser # Top anchor now in skin $full = $full.$toc; } + + # wrap each section in a div if $wgSectionContainers is set to true + if ( $wgSectionContainers ) { + if( !empty( $head[$i] ) ) { # if there's no next header, then don't try to close out any existing sections here + # get the level of the next header section + preg_match('/ 0 ) { + $hLevel = $hLevelMatches[1]; + if ( $i != 0 ) { # we don't have an open div for section 0, so don't try to close it + # close any open divs for sections with headers that are <= to the next header level + $this->closeSectionContainers( $hLevel, &$currentHLevel, &$full, &$openDivs); + } + $currentHLevel = $hLevel; + } + } + + # open the div for the next header, if there is one + if ( isset($currentHLevel) && !empty( $head[$i] ) ) { + $full .= '
'; + array_push($openDivs, array($currentHLevel, $i)); + } + + # if we've outputed the last section of the article, close any open divs that are remaining + if ( $i == ( count($blocks) - 1) && isset($currentHLevel) ) { + $this->closeSectionContainers( $hLevel, &$currentHLevel, &$full, &$openDivs); + } + } if( !empty( $head[$i] ) ) { $full .= $head[$i]; @@ -3685,6 +3717,29 @@ class Parser } } + /** + * Analyze the header level of the current and next section being parsed to + * determine if any already parsed sections need to be closed + * + * @param string $hLevel the level of the next header to be parsed + * @param string $currentHLevel the level of the last parsed header + * @param string $full a reference to the string that stores the output of the parser + * @param array $openDivs a reference to the array that stores a list of open section containers + * @return true + */ + function closeSectionContainers( $hLevel, &$currentHLevel, &$full, &$openDivs) { + while ( $hLevel <= $currentHLevel ) { + $full .= '
'; + $popped = array_pop($openDivs); + if ( count($openDivs) ) { + $currentHLevel = $openDivs[count($openDivs) - 1][0]; + } else { + break; + } + } + return true; + } + /** * Transform wiki markup when saving a page by doing \r\n -> \n * conversion, substitting signatures, {{subst:}} templates, etc. -- 2.20.1