Added an extension, called EditSectionHiliteLink, that highlights the appropriate...
authorArash Boostani <aboostani@users.mediawiki.org>
Tue, 5 May 2009 22:49:45 +0000 (22:49 +0000)
committerArash Boostani <aboostani@users.mediawiki.org>
Tue, 5 May 2009 22:49:45 +0000 (22:49 +0000)
extensions/EditSectionHiliteLink/EditSectionHiliteLink.css [new file with mode: 0644]
extensions/EditSectionHiliteLink/EditSectionHiliteLink.hooks.php [new file with mode: 0644]
extensions/EditSectionHiliteLink/EditSectionHiliteLink.js [new file with mode: 0644]
extensions/EditSectionHiliteLink/EditSectionHiliteLink.php [new file with mode: 0644]
includes/parser/Parser.php

diff --git a/extensions/EditSectionHiliteLink/EditSectionHiliteLink.css b/extensions/EditSectionHiliteLink/EditSectionHiliteLink.css
new file mode 100644 (file)
index 0000000..0621dde
--- /dev/null
@@ -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 (file)
index 0000000..0d8851c
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Hooks for EditSectionHiliteLink extension
+ *
+ * @file
+ * @ingroup Extensions
+ */
+
+class EditSectionHiliteLinkHooks {
+
+       /* Static Functions */
+
+       /**
+        * interceptLink hook
+        */
+       public static function interceptLink($this, $nt, $section, $tooltip, &$result)  {
+               global $wgSectionContainers;
+               
+               if ( $wgSectionContainers ) {
+                       $section = $section -1;
+                       $section_name = 'section_' . $section . '_container';
+                       $result = preg_replace('/(\D+)( title=)(\D+)/', '${1} onmouseover="editSectionHiliteOn(\'' . $section_name . '\')" onmouseout="editSectionHiliteOff(\'' . $section_name . '\')" title=$3', $result);
+               }
+               return true;
+       }
+
+       /**
+        * AjaxAddScript hook
+        * Add ajax support script
+        */
+       public static function addJS(
+               $out
+       ) {
+               global $wgScriptPath, $wgJsMimeType, $wgEditSectionHiliteLinkStyleVersion;
+               // FIXME: assumes standard dir structure
+               // Add javascript to support section edit link highlighting saving
+               $out->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 (file)
index 0000000..acf509b
--- /dev/null
@@ -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 (file)
index 0000000..8ba3d85
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/**
+ * EditSectionHiliteLink extension
+ *
+ * @file
+ * @ingroup Extensions
+ *
+ * This file contains the main include file for the EditSectionHiliteLink extension of
+ * MediaWiki.
+ *
+ * Usage: Add the following line in LocalSettings.php:
+ * require_once( "$IP/extensions/EditSectionHiliteLink/EditSectionHiliteLink.php" );
+ *
+ * @author Arash Boostani <aboostani@wikimedia.org>
+ * @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
index 0f57d57..fa0b57d 100644 (file)
@@ -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].*?' . '>.*?<\/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('/<H([0-6])/i', $head[$i], $hLevelMatches);
+                               
+                                       if ( count($hLevelMatches) > 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 .= '<div id="section_' . $i . '_container">';
+                                        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 .= '</div>';
+                       $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.