static function processArticleHTML($body, $opts = array()) { global $wgUser, $wgTitle, $wgLanguageCode; $doc = PHPQuery::newDocument($body); $featurestar = pq("div#featurestar"); if ($featurestar) { $clearelement = pq($featurestar)->next(); $clearelement->remove(); $featurestar->remove(); } $ads = $wgUser->isAnon() && !@$opts['no-ads'] && wikihowAds::isEligibleForAds(); // Remove __TOC__ resulting html from all pages other than User pages if (@$opts['ns'] != NS_USER && pq('div#toc')->length) { $toc = pq('div#toc'); //in upgrade, it's no longer preceded by an h2, so deleting the intro instead :( //maybe this will change so leaving in for now. //$toc->prev()->remove(); $toc->remove(); } $sticky = ""; if (@$opts['sticky-headers']) { $sticky = " sticky "; } // Remove originators for titles that don't exist if ($wgTitle->getArticleId() == 0) { pq('#originators')->remove(); } //move firstHeading to inside the intro $firstH2 = pq("h2:first"); if (pq($firstH2)->length() == 0) { try { pq("#bodycontents")->children(":first")->wrapAll("<div class='section wh_block'></div>"); } catch (Exception $e) { } } else { try { pq($firstH2)->prevAll()->reverse()->wrapAll("<div id='intro' class='section {$sticky}'></div>"); } catch (Exception $e) { } } //add a clearall to the end of the intro pq("#intro")->append("<div class='clearall'></div>"); //removing any stray br tags at the start of the intro foreach (pq("#intro #originators")->next()->children() as $child) { if (pq($child)->is("br")) { pq($child)->remove(); } else { break; } } //add the pimpedheader to our h3s! pq('h3, h4')->prepend('<div class="altblock"></div>'); foreach (pq("h2") as $node) { $h2Parent = pq($node)->parent(); if (@$opts['ns'] == NS_USER && pq($h2Parent)->attr("id") == "toctitle") { pq("#toc")->wrapAll("<div class='section'></div>"); pq("#toc ul:first")->addClass("section_text"); continue; } //find each section //first grab the name $sectionName = mb_strtolower(pq("span.mw-headline", $node)->html()); //Remove all non-letters and numbers in all languges if ($wgLanguageCode == 'en') { $sectionName = preg_replace("/[^A-Za-z0-9]/u", '', $sectionName); } elseif ($wgLanguageCode == 'hi') { $sectionName = str_replace(' ', '', $sectionName); } else { $sectionName = preg_replace("/[^\\p{L}\\p{N}]/u", '', $sectionName); } //now find all the elements prior to the next h2 $set = array(); $h3Tags = array(); $h3Elements = array(); $priorToH3Set = array(); $h3Count = 0; foreach (pq($node)->nextAll() as $sibling) { if (pq($sibling)->is("h2")) { break; } if (pq($sibling)->is("h3")) { $h3Count++; $h3Tags[$h3Count] = $sibling; $h3Elements[$h3Count] = array(); } else { if ($h3Count > 0) { $h3Elements[$h3Count][] = $sibling; } else { $priorToH3Set[] = $sibling; } } $set[] = $sibling; } if (mb_strtolower($sectionName) == mb_strtolower(wfMessage('steps')->text())) { if ($h3Count > 0) { //has alternate methods $altMethodNames = array(); $altMethodAnchors = array(); if (count($priorToH3Set) > 0) { //needs to have a steps section prior to the //alt method try { pq($priorToH3Set)->wrapAll("<div id='{$sectionName}' class='section_text'></div>"); } catch (Exception $e) { } $overallSet = array(); $overallSet[] = $node; foreach (pq("div#{$sectionName}:first") as $temp) { $overallSet[] = $temp; } try { pq($overallSet)->wrapAll("<div class='section steps {$sticky}'></div>"); } catch (Exception $e) { } } else { //hide the h2 tag pq($node)->addClass("hidden"); } $stepsEditUrl = pq('.editsection', $node)->attr("href"); $displayMethodCount = $h3Count; $isSample = array(); for ($i = 1; $i <= $h3Count; $i++) { $isSampleItem = false; if (!is_array($h3Elements[$i]) || count($h3Elements[$i]) < 1) { $isSampleItem = false; } else { //the sd_container isn't always the first element, need to look through all foreach ($h3Elements[$i] as $node) { //not the most efficient way to do this, but couldn't get the find function to work. if (pq($node)->attr("id") == "sd_container") { $isSampleItem = true; break; } } } if ($isSampleItem) { $isSample[$i] = true; $displayMethodCount--; } else { $isSample[$i] = false; } } if ($ads) { wikihowAds::setAltMethods($displayMethodCount > 1); } //[sc] ***INTERMEDIATE STEP (remove line below) $wikihowArticle = WikihowArticleEditor::newFromTitle($wgTitle); $hasParts = $opts['magic-word'] == MagicWord::get('parts'); $displayMethod = 1; for ($i = 1; $i <= $h3Count; $i++) { //change the method title $methodTitle = pq("span.mw-headline", $h3Tags[$i])->html(); //[sc] ***INTERMEDIATE STEP (remove line below) $removeRet = WikihowArticleEditor::removeMethodNamePrefix($methodTitle); $altMethodNames[] = $methodTitle; $altMethodAnchors[] = pq("span.mw-headline", $h3Tags[$i])->attr("id"); //[sc] ***INTERMEDIATE STEP (swap if logic below) //if ($displayMethodCount > 1 && $hasParts && $opts['ns'] == NS_MAIN) { if ($displayMethodCount > 1 && !$isSample[$i] && ($removeRet['has_parts'] || $hasParts) && $opts['ns'] == NS_MAIN) { if ($methodTitle) { $methodTitle = wfMessage("part_2", $displayMethod, $displayMethodCount, $methodTitle)->text(); } else { $methodTitle = wfMessage("part_1", $displayMethod, $displayMethodCount)->text(); } $displayMethod++; } elseif ($displayMethodCount > 1 && !$isSample[$i] && $opts['ns'] == NS_MAIN) { if ($methodTitle) { $methodTitle = wfMessage("method_2", $displayMethod, $displayMethodCount, $methodTitle)->text(); } else { $methodTitle = wfMessage("method_1", $displayMethod, $displayMethodCount)->text(); } $displayMethod++; } pq("span.mw-headline", $h3Tags[$i])->html($methodTitle); //add our custom anchors $anchor_name = pq("span.mw-headline", $h3Tags[$i])->attr('id') . '_sub'; try { pq($h3Tags[$i])->before('<a name="' . $anchor_name . '" class="anchor"></a>'); } catch (Exception $e) { } //want to change the url for the edit link to //edit the whole steps section, not just the //alternate method pq(".editsection", $h3Tags[$i])->attr("href", $stepsEditUrl); $sample = $isSample[$i] ? "sample" : ""; //only wrap if there's stuff there to wrap. //This happens when people put two sub methods on top of each other without //any content between. if (count($h3Elements[$i]) > 0) { pq($h3Elements[$i])->wrapAll("<div id='{$sectionName}_{$i}' class='section_text'></div>"); } $overallSet = array(); $overallSet[] = $h3Tags[$i]; foreach (pq("div#{$sectionName}_{$i}:first") as $temp) { $overallSet[] = $temp; } try { pq($overallSet)->wrapAll("<div class='section steps {$sample} {$sticky}'></div>"); } catch (Exception $e) { } } //BEBETH - not sure we need this anymore, but not sure yet //fix for Chrome -- wrap first anchor name so it detects the spacing try { pq(".section.steps:first")->prev()->children(".anchor")->after('<br class="clearall" />')->wrapAll('<div></div>'); } catch (Exception $e) { } //now we should have all the alt methods, //let's create the links to them under the headline $charCount = 0; $maxCount = 80000; //temporarily turning off hidden headers $hiddenCount = 0; $anchorList = ""; for ($i = 0; $i < count($altMethodAnchors); $i++) { $methodName = pq('<div>' . $altMethodNames[$i] . '</div>')->text(); // remove any reference notes $methodName = preg_replace("@\\[\\d{1,3}\\]\$@", "", $methodName); $charCount += strlen($methodName); $class = ""; if ($charCount > $maxCount) { $class = "hidden excess"; $hiddenCount++; } if ($methodName == "") { continue; } $anchorList .= "<a href='#{$altMethodAnchors[$i]}_sub' class='{$class}'>{$methodName}</a>"; } $hiddentext = ""; if ($hiddenCount > 0) { $hiddenText = "<a href='#' id='method_toc_unhide'>{$hiddenCount} more method" . ($hiddenCount > 1 ? "s" : "") . "</a>"; $hiddenText .= "<a href='#' id='method_toc_hide' class='hidden'>show less methods</a>"; } else { $hiddenText = ''; } //add our little list header if ($hasParts) { //ucwords $anchorList = '<span>' . ucwords(Misc::numToWord(count($altMethodAnchors), 10)) . ' ' . wfMessage('part_3')->text() . ':</span>' . $anchorList; } else { $anchorList = '<span>' . ucwords(Misc::numToWord(count($altMethodAnchors), 10)) . ' ' . wfMessage('method_3')->text() . ':</span>' . $anchorList; } //chance to reformat the alt method_toc before output //using for running tests $bAfter = false; wfRunHooks('BeforeOutputAltMethodTOC', array($wgTitle, &$anchorList, &$bAfter)); $bAfter = true; if ($bAfter) { pq("#originators")->after("<p id='method_toc' style='margin-top:-10px'>{$anchorList}{$hiddenText}</p>"); } else { pq(".firstHeading")->after("<p id='method_toc'>{$anchorList}{$hiddenText}</p>"); } } else { //only 1 method if ($ads) { wikihowAds::setAltMethods(false); } if ($set) { try { pq($set)->wrapAll("<div id='{$sectionName}' class='section_text'></div>"); } catch (Exception $e) { } } $overallSet = array(); $overallSet[] = $node; foreach (pq("div#{$sectionName}:first") as $temp) { $overallSet[] = $temp; } try { pq($overallSet)->wrapAll("<div class='section steps {$sticky}'></div>"); } catch (Exception $e) { } } } else { //not a steps section if ($set) { $sec_id = @$opts['list-page'] ? '' : 'id="' . $sectionName . '"'; try { $new_set = pq($set)->wrapAll("<div {$sec_id} class='section_text'></div>"); } catch (Exception $e) { } } $overallSet = array(); $overallSet[] = $node; foreach (pq("div#{$sectionName}:first") as $temp) { $overallSet[] = $temp; } try { pq($overallSet)->wrapAll("<div class='section {$sectionName} {$sticky}'></div>"); } catch (Exception $e) { } if (@$opts['list-page']) { //gotta pull those dangling divs into the same space as the h2 try { pq($overallSet)->parent()->append(pq($new_set)); } catch (Exception $e) { } } // commenting this out because it's causing the following error: // "Couldn't add newnode as the previous sibling of refnode" // // format edit links for non-steps sections // // pq('span', $node)->prepend(pq('a.edit', $node)); //remove the edit link from subheaders if we're not in the steps section try { pq(".{$sectionName} h3 .editsection")->remove(); } catch (Exception $e) { } } } //add a clear to the end of each section_text to make sure //images don't bleed across the bottom pq(".section_text")->append("<div class='clearall'></div>"); // Add checkboxes to Ingredients and 'Things You Need' sections, but only to the top-most li $lis = pq('#ingredients > ul > li, #thingsyoullneed > ul > li'); foreach ($lis as $li) { $id = md5(pq($li)->html() . mt_rand(1, 100)); pq($li)->html("<input id='item_{$id}' class='css-checkbox' type='checkbox'/><label for='item_{$id}' name='item_{$id}_lbl' class='css-checkbox-label'></label><div class='checkbox-text'>" . pq($li)->html() . '</div>'); } // Move templates above article body contents and style appropriately foreach (pq('.template_top') as $template) { pq($template)->addClass('sidebox'); if (pq($template)->parent()->hasClass('tmp_li')) { pq($template)->addClass('tmp_li'); } if ($wgUser->isAnon()) { pq($template)->addClass('notice_bgcolor_lo'); } else { pq($template)->addClass('notice_bgcolor_important'); } } // put templates after the intro div pq('.template_top')->insertAfter('#intro'); //now put the step numbers in foreach (pq("div.steps .section_text > ol") as $list) { pq($list)->addClass("steps_list_2"); $stepNum = 1; foreach (pq($list)->children() as $step) { $boldStep = WikihowArticleHTML::boldFirstSentence(pq($step)->html()); pq($step)->html($boldStep); pq($step)->prepend("<div class='step_num'>{$stepNum}</div>"); pq($step)->append("<div class='clearall'></div>"); $stepNum++; } } foreach (pq(".steps:last .steps_list_2")->children(":last-child") as $step) { pq($step)->addClass("final_li"); } //move each of the large images to the top foreach (pq(".steps_list_2 li .mwimg.largeimage") as $image) { //delete any previous <br> foreach (pq($image)->prevAll() as $node) { if (pq($node)->is("br")) { pq($node)->remove(); } else { break; } } //first handle the special case where the image //ends up inside the bold tag by accident if (pq($image)->parent()->is("b")) { pq($image)->insertBefore(pq($image)->parent()); } if (pq($image)->parent()->parent()->is(".steps_list_2")) { pq($image)->parent()->prepend($image); } } //move each of the large images to the top foreach (pq(".steps_list_2 li .whvid_cont") as $vid) { //delete any previous <br> foreach (pq($vid)->prevAll() as $node) { if (pq($node)->is("br")) { pq($node)->remove(); } else { break; } } if (pq($vid)->parent()->parent()->is(".steps_list_2")) { pq($vid)->parent()->prepend($vid); } } //if there's a related articles section, make it have images $relatedSection = pq("#relatedwikihows"); if ($relatedSection) { foreach (pq("li a", $relatedSection) as $related) { $titleText = pq($related)->attr("title"); $title = Title::newFromText($titleText); if ($title) { $image = SkinWikihowskin::getArticleThumb($title, 127, 120); pq($relatedSection)->prepend($image); } pq($related)->remove(); } pq("ul", $relatedSection)->remove(); pq($relatedSection)->append("<div class='clearall'></div>"); } //remove all images in the intro that aren't //marked with the class "introimage" pq("#intro .mwimg:not(.introimage)")->remove(); //let's mark all the <p> tags that aren't inside a step. //they need special padding foreach (pq(".section.steps p") as $p) { if (pq($p)->parents(".steps_list_2")->count() == 0 && pq($p)->children(".anchor")->count() == 0) { pq($p)->addClass("lone_p"); } } // Add alt method adder cta if (class_exists("AltMethodAdder") && $wgTitle && $wgUser && $wgUser->isAnon()) { $cta = AltMethodAdder::getCTA($wgTitle); if (!is_null($cta)) { pq("div.steps:last")->after($cta); } } //add line breaks between the p tags foreach (pq("p") as $paragraph) { $sibling = pq($paragraph)->next(); if (!pq($sibling)->is("p")) { continue; } if (pq($sibling)->children(":first")->hasClass("anchor")) { continue; } $id = pq($paragraph)->attr("id"); if ($id == "originators" || $id == "method_toc") { continue; } pq($paragraph)->after("<br />"); } if ($ads) { pq(".#intro")->append(wikihowAds::getAdUnitPlaceholder('intro')); pq(".steps_list_2:first li:first")->append(wikihowAds::getAdUnitPlaceholder(0)); pq(".final_li")->append(wikihowAds::getAdUnitPlaceholder(1)); $tipsClass = mb_strtolower(wfMessage("tips")->text()); //grabs the tips section by name, but internationalized pq(".{$tipsClass} .section_text")->children()->filter("ul:last")->after(wikihowAds::getAdUnitPlaceholder('2a')); //add in the Taboola ads if ($wgLanguageCode == "en") { $sourcesClass = mb_strtolower(wfMessage("sources")->text()); //grabs the sources and citations section by name, but internationalized $sourcesClass = str_replace(' ', '', $sourcesClass); if (pq(".section.{$sourcesClass}")->length) { //put above Sources & Citations if it exists pq(".section.{$sourcesClass}")->before(wikihowAds::getAdUnitTaboola()); } else { // put above Article Info pq("#bodycontents")->after(wikihowAds::getAdUnitTaboola()); } } } $markPatrolledLink = self::getMarkPatrolledLink(); if ($markPatrolledLink) { pq('#bodycontents')->append($markPatrolledLink); } // //TEST - no intro // global $wgRequest; // $article_ids = explode("\n",ConfigStorage::dbGetConfig('wikihow-nointro-test')); // if ($wgTitle && $wgTitle->getNamespace() == NS_MAIN && $wgRequest->getVal('action') == '' && in_array($wgTitle->getArticleID(),$article_ids)) { // pq('#intro p:last')->remove(); // } return $doc->htmlOuter(); }
static function processArticleHTML($body, $opts = array()) { global $wgUser, $wgTitle, $wgLanguageCode; $skin = $wgUser->getSkin(); $doc = PHPQuery::newDocument($body); $featurestar = pq("div#featurestar"); if ($featurestar) { $clearelement = pq($featurestar)->next(); $clearelement->remove(); $featurestar->remove(); } $ads = $wgUser->isAnon() && !@$opts['no-ads'] && wikihowAds::isEligibleForAds(); // Remove __TOC__ resulting html from all pages other than User pages if (@$opts['ns'] != NS_USER && pq('table#toc')->length) { $toc = pq('table#toc'); $toc->prev()->remove(); $toc->remove(); } $sticky = ""; if (@$opts['sticky-headers']) { $sticky = " sticky "; } // Remove originators for titles that don't exist if ($wgTitle->getArticleId() == 0) { pq('#originators')->remove(); } //move firstHeading to inside the intro $firstH2 = pq("h2:first"); if (pq($firstH2)->length() == 0) { try { pq("#bodycontents")->children(":first")->wrapAll("<div class='section wh_block'></div>"); } catch (Exception $e) { } } else { try { pq($firstH2)->prevAll()->reverse()->wrapAll("<div id='intro' class='section {$sticky}'></div>"); } catch (Exception $e) { } } //add a clearall to the end of the intro pq("#intro")->append("<div class='clearall'></div>"); //removing any stray br tags at the start of the intro foreach (pq("#intro #originators")->next()->children() as $child) { if (pq($child)->is("br")) { pq($child)->remove(); } else { break; } } //add the pimpedheader to our h3s! pq('h3, h4')->prepend('<div class="altblock"></div>'); foreach (pq("h2") as $node) { //find each section //first grab the name $sectionName = mb_strtolower(pq("span", $node)->html()); //Remove all non-letters and numbers in all languges if ($wgLanguageCode == 'en') { $sectionName = preg_replace("/[^A-Za-z0-9]/u", '', $sectionName); } elseif ($wgLanguageCode == 'hi') { $sectionName = str_replace(' ', '', $sectionName); } else { $sectionName = preg_replace("/[^\\p{L}\\p{N}]/u", '', $sectionName); } //now find all the elements prior to the next h2 $set = array(); $h3Tags = array(); $h3Elements = array(); $priorToH3Set = array(); $h3Count = 0; foreach (pq($node)->nextAll() as $sibling) { if (pq($sibling)->is("h2")) { break; } if (pq($sibling)->is("h3")) { $h3Count++; $h3Tags[$h3Count] = $sibling; $h3Elements[$h3Count] = array(); } else { if ($h3Count > 0) { $h3Elements[$h3Count][] = $sibling; } else { $priorToH3Set[] = $sibling; } } $set[] = $sibling; } if (mb_strtolower($sectionName) == mb_strtolower(wfMsg('steps'))) { if ($h3Count > 0) { //has alternate methods $altMethodNames = array(); $altMethodAnchors = array(); if (count($priorToH3Set) > 1) { //if there are alt methods, then there will at least be a <p> tag with a link inside, so that doesn't count //needs to have a steps section prior to the //alt method try { pq($priorToH3Set)->wrapAll("<div id='{$sectionName}' class='section_text'></div>"); } catch (Exception $e) { } $overallSet = array(); $overallSet[] = $node; foreach (pq("div#{$sectionName}:first") as $temp) { $overallSet[] = $temp; } try { pq($overallSet)->wrapAll("<div class='section steps {$sticky}'></div>"); } catch (Exception $e) { } } else { //hide the h2 tag pq($node)->addClass("hidden"); } $displayMethodCount = $h3Count; $isSample = array(); for ($i = 1; $i <= $h3Count; $i++) { $isSampleItem = false; if (!is_array($h3Elements[$i]) || count($h3Elements[$i]) < 1) { $isSampleItem = false; } else { //the sd_container isn't always the first element, need to look through all foreach ($h3Elements[$i] as $node) { //not the most efficient way to do this, but couldn't get the find function to work. if (pq($node)->attr("id") == "sd_container") { $isSampleItem = true; break; } } } if ($isSampleItem) { $isSample[$i] = true; $displayMethodCount--; } else { $isSample[$i] = false; } } if ($ads) { wikihowAds::setAltMethods($displayMethodCount > 1); } $wikihowArticle = WikihowArticleEditor::newFromTitle($wgTitle); $editLink = $skin->editSectionLink($wgTitle, $wikihowArticle->getSectionNumber("steps")); $displayMethod = 1; for ($i = 1; $i <= $h3Count; $i++) { //change the method title $methodTitle = pq("span", $h3Tags[$i])->html(); $removeRet = WikihowArticleEditor::removeMethodNamePrefix($methodTitle); $altMethodNames[] = $methodTitle; if ($displayMethodCount > 1 && !$isSample[$i] && $removeRet['has_parts'] && $opts['ns'] == NS_MAIN) { if ($methodTitle) { $methodTitle = wfMsg("part_2", $displayMethod, $displayMethodCount, $methodTitle); } else { $methodTitle = wfMsg("part_1", $displayMethod, $displayMethodCount); } $displayMethod++; } elseif ($displayMethodCount > 1 && !$isSample[$i] && $opts['ns'] == NS_MAIN) { if ($methodTitle) { $methodTitle = wfMsg("method_2", $displayMethod, $displayMethodCount, $methodTitle); } else { $methodTitle = wfMsg("method_1", $displayMethod, $displayMethodCount); } $displayMethod++; } pq("span", $h3Tags[$i])->html($methodTitle); //add an edit link to each sub method pq("span", $h3Tags[$i])->prepend($editLink); $sample = $isSample[$i] ? "sample" : ""; pq($h3Elements[$i])->wrapAll("<div id='{$sectionName}_{$i}' class='section_text'></div>"); $overallSet = array(); $overallSet[] = $h3Tags[$i]; foreach (pq("div#{$sectionName}_{$i}:first") as $temp) { $overallSet[] = $temp; } try { pq($overallSet)->wrapAll("<div class='section steps {$sample} {$sticky}'></div>"); } catch (Exception $e) { } } $i = 1; // Pull out the top-level anchors foreach (pq(".section.steps") as $steps) { // Only grab last anchor. There may be other anchors for subsections // but we'll ignore those $anchor = pq('.anchor:last', $steps); $altMethodAnchors[$i] = pq($anchor)->attr("name"); $i++; } //now grab the one prior to the first step $altMethodAnchors[0] = pq(".section.steps:first")->prev()->children(".anchor")->attr("name"); // Sometimes there isn't an anchor prior to first step, so get rid of it if (empty($altMethodAnchors[0])) { $altMethodAnchors = array_splice($altMethodAnchors, 0); } //fix for Chrome -- wrap first anchor name so it detects the spacing try { pq(".section.steps:first")->prev()->children(".anchor")->after('<br class="clearall" />')->wrapAll('<div></div>'); } catch (Exception $e) { } //now we should have all the alt methods, //let's create the links to them under the headline $charCount = 0; $maxCount = 80000; //temporairily turning off hidden headers $hiddenCount = 0; $anchorList = ""; //don't use the last altMethodAnchor b/c it links to the first non-step section for ($i = 0; $i < count($altMethodAnchors) - 1; $i++) { $methodName = pq('<div>' . $altMethodNames[$i] . '</div>')->text(); // remove any reference notes $methodName = preg_replace("@\\[\\d{1,3}\\]\$@", "", $methodName); $charCount += strlen($methodName); $class = ""; if ($charCount > $maxCount) { $class = "hidden excess"; $hiddenCount++; } if ($methodName == "") { continue; } $anchorList .= "<a href='#{$altMethodAnchors[$i]}' class='{$class}'>{$methodName}</a>"; } $hiddentext = ""; if ($hiddenCount > 0) { $hiddenText = "<a href='#' id='method_toc_unhide'>{$hiddenCount} more method" . ($hiddenCount > 1 ? "s" : "") . "</a>"; $hiddenText .= "<a href='#' id='method_toc_hide' class='hidden'>show less methods</a>"; } pq(".firstHeading")->after("<p id='method_toc'>{$anchorList}{$hiddenText}</p>"); } else { //only 1 method if ($ads) { wikihowAds::setAltMethods(false); } if ($set) { try { pq($set)->wrapAll("<div id='{$sectionName}' class='section_text'></div>"); } catch (Exception $e) { } } $overallSet = array(); $overallSet[] = $node; foreach (pq("div#{$sectionName}:first") as $temp) { $overallSet[] = $temp; } try { pq($overallSet)->wrapAll("<div class='section steps {$sticky}'></div>"); } catch (Exception $e) { } } } else { //not a steps section if ($set) { $sec_id = @$opts['list-page'] ? '' : 'id="' . $sectionName . '"'; try { $new_set = pq($set)->wrapAll("<div {$sec_id} class='section_text'></div>"); } catch (Exception $e) { } } $overallSet = array(); $overallSet[] = $node; foreach (pq("div#{$sectionName}:first") as $temp) { $overallSet[] = $temp; } try { pq($overallSet)->wrapAll("<div class='section {$sectionName} {$sticky}'></div>"); } catch (Exception $e) { } if (@$opts['list-page']) { //gotta pull those dangling divs into the same space as the h2 pq($overallSet)->parent()->append(pq($new_set)); } // commenting this out because it's causing the following error: // "Couldn't add newnode as the previous sibling of refnode" // // format edit links for non-steps sections // // pq('span', $node)->prepend(pq('a.edit', $node)); } } //add a clear to the end of each section_text to make sure //images don't bleed across the bottom pq(".section_text")->append("<div class='clearall'></div>"); // Add checkboxes to Ingredients and 'Things You Need' sections, but only to the top-most li $lis = pq('#ingredients > ul > li, #thingsyoullneed > ul > li'); foreach ($lis as $li) { $id = md5(pq($li)->html() . mt_rand(1, 100)); pq($li)->html("<input id='item_{$id}' class='css-checkbox' type='checkbox'/><label for='item_{$id}' name='item_{$id}_lbl' class='css-checkbox-label'></label><div class='checkbox-text'>" . pq($li)->html() . '</div>'); } // Move templates above article body contents and style appropriately foreach (pq('.template_top') as $template) { pq($template)->addClass('sidebox'); if (pq($template)->parent()->hasClass('tmp_li')) { pq($template)->addClass('tmp_li'); } if ($wgUser->isAnon()) { pq($template)->addClass('notice_bgcolor_lo'); } else { pq($template)->addClass('notice_bgcolor_important'); } } // put templates after the intro div pq('.template_top')->insertAfter('#intro'); //now put the step numbers in foreach (pq("div.steps .section_text > ol") as $list) { pq($list)->addClass("steps_list_2"); $stepNum = 1; foreach (pq($list)->children() as $step) { $boldStep = WikihowArticleHTML::boldFirstSentence(pq($step)->html()); pq($step)->html($boldStep); pq($step)->prepend("<div class='step_num'>{$stepNum}</div>"); pq($step)->append("<div class='clearall'></div>"); $stepNum++; } } foreach (pq(".steps:last .steps_list_2")->children(":last-child") as $step) { pq($step)->addClass("final_li"); } //move each of the large images to the top foreach (pq(".steps_list_2 li .mwimg.largeimage") as $image) { //delete any previous <br> foreach (pq($image)->prevAll() as $node) { if (pq($node)->is("br")) { pq($node)->remove(); } else { break; } } //first handle the special case where the image //ends up inside the bold tag by accident if (pq($image)->parent()->is("b")) { pq($image)->insertBefore(pq($image)->parent()); } if (pq($image)->parent()->parent()->is(".steps_list_2")) { pq($image)->parent()->prepend($image); } } //move each of the large images to the top foreach (pq(".steps_list_2 li .whvid_cont") as $vid) { //delete any previous <br> foreach (pq($vid)->prevAll() as $node) { if (pq($node)->is("br")) { pq($node)->remove(); } else { break; } } if (pq($vid)->parent()->parent()->is(".steps_list_2")) { pq($vid)->parent()->prepend($vid); } } //if there's a related articles section, make it have images $relatedSection = pq("#relatedwikihows"); if ($relatedSection) { foreach (pq("li a", $relatedSection) as $related) { $titleText = pq($related)->attr("title"); $title = Title::newFromText($titleText); if ($title) { $image = $skin->getArticleThumb($title, 127, 120); pq($relatedSection)->prepend($image); } pq($related)->remove(); } pq("ul", $relatedSection)->remove(); pq($relatedSection)->append("<div class='clearall'></div>"); } //remove all images in the intro that aren't //marked with the class "introimage" pq("#intro .mwimg:not(.introimage)")->remove(); //let's mark all the <p> tags that aren't inside a step. //they need special padding foreach (pq(".section.steps p") as $p) { if (pq($p)->parents(".steps_list_2")->count() == 0 && pq($p)->children(".anchor")->count() == 0) { pq($p)->addClass("lone_p"); } } // Add alt method adder cta if (class_exists("AltMethodAdder") && $wgTitle && $wgUser && $wgUser->isAnon()) { $cta = AltMethodAdder::getCTA($wgTitle); if (!is_null($cta)) { pq("div.steps:last")->after($cta); } } //add line breaks between the p tags foreach (pq("p") as $paragraph) { $sibling = pq($paragraph)->next(); if (!pq($sibling)->is("p")) { continue; } if (pq($sibling)->children(":first")->hasClass("anchor")) { continue; } $id = pq($paragraph)->attr("id"); if ($id == "originators" || $id == "method_toc") { continue; } pq($paragraph)->after("<br />"); } if ($ads) { pq("#intro")->append(wikihowAds::getAdUnitPlaceholder('intro')); pq(".steps_list_2:first li:first")->append(wikihowAds::getAdUnitPlaceholder(0)); pq(".final_li")->append(wikihowAds::getAdUnitPlaceholder(1)); $tipsClass = mb_strtolower(wfMsg("tips")); //grabs the tips section by name, but internationalized pq(".{$tipsClass} ul:last")->after(wikihowAds::getAdUnitPlaceholder('2a')); } return $doc->htmlOuter(); }