/** * Return the difference between two HTML documents. * @param String $a The first HTML document * @param String $b The second HTML document * @param Boolean $describe_formatting_changes If true, changes in the formatting (for example adding a certain HTML attribute * to a tag) are shown in text form. * @return String An HTML document that represents the difference between the two HTML documents by assigning the class names * diff-html-added and diff-html-removed to the changed elements. */ function html_diff($a, $b, $describe_formatting_changes = false) { $out = new ChangeText(); $htmldiffer = new HTMLDiffer(new DelegatingContentHandler($out)); $htmldiffer->htmlDiff($a, $b, $describe_formatting_changes); return $out->toString(); }
function htmlDiff($from, $to) { // Create an XML parser $xml_parser = xml_parser_create(''); $domfrom = new DomTreeBuilder(); // Set the functions to handle opening and closing tags xml_set_element_handler($xml_parser, array($domfrom, "startElement"), array($domfrom, "endElement")); // Set the function to handle blocks of character data xml_set_character_data_handler($xml_parser, array($domfrom, "characters")); HTMLDiffer::diffDebug("Parsing " . strlen($from) . " characters worth of HTML\n"); if (!xml_parse($xml_parser, '<?xml version="1.0" encoding="UTF-8"?>' . Sanitizer::hackDocType() . '<body>', false) || !xml_parse($xml_parser, $from, false) || !xml_parse($xml_parser, '</body>', true)) { $error = xml_error_string(xml_get_error_code($xml_parser)); $line = xml_get_current_line_number($xml_parser); $col = xml_get_current_column_number($xml_parser); HTMLDiffer::diffDebug("XML error: {$error} at line {$line} and column {$col}\n"); } xml_parser_free($xml_parser); unset($from); $xml_parser = xml_parser_create(''); $domto = new DomTreeBuilder(); // Set the functions to handle opening and closing tags xml_set_element_handler($xml_parser, array($domto, "startElement"), array($domto, "endElement")); // Set the function to handle blocks of character data xml_set_character_data_handler($xml_parser, array($domto, "characters")); HTMLDiffer::diffDebug("Parsing " . strlen($to) . " characters worth of HTML\n"); if (!xml_parse($xml_parser, '<?xml version="1.0" encoding="UTF-8"?>' . Sanitizer::hackDocType() . '<body>', false) || !xml_parse($xml_parser, $to, false) || !xml_parse($xml_parser, '</body>', true)) { $error = xml_error_string(xml_get_error_code($xml_parser)); $line = xml_get_current_line_number($xml_parser); $col = xml_get_current_column_number($xml_parser); HTMLDiffer::diffDebug("XML error: {$error} at line {$line} and column {$col}\n"); } xml_parser_free($xml_parser); unset($to); $diffengine = new WikiDiff3(); $differences = $this->preProcess($diffengine->diff_range($domfrom->getDiffLines(), $domto->getDiffLines())); unset($xml_parser, $diffengine); $textNodeDiffer = new TextNodeDiffer($domto, $domfrom); $currentIndexLeft = 0; $currentIndexRight = 0; foreach ($differences as &$d) { if ($d->leftstart > $currentIndexLeft) { $textNodeDiffer->handlePossibleChangedPart($currentIndexLeft, $d->leftstart, $currentIndexRight, $d->rightstart); } if ($d->leftlength > 0) { $textNodeDiffer->markAsDeleted($d->leftstart, $d->leftend, $d->rightstart); } $textNodeDiffer->markAsNew($d->rightstart, $d->rightend); $currentIndexLeft = $d->leftend; $currentIndexRight = $d->rightend; } $oldLength = $textNodeDiffer->lengthOld(); if ($currentIndexLeft < $oldLength) { $textNodeDiffer->handlePossibleChangedPart($currentIndexLeft, $oldLength, $currentIndexRight, $textNodeDiffer->lengthNew()); } $textNodeDiffer->expandWhiteSpace(); $output = new HTMLOutput('htmldiff'); return $output->parse($textNodeDiffer->bodyNode); }
function __construct(TagNode $parent, $qName, $attrs) { if (strcasecmp($qName, 'img') == 0 && !array_key_exists('src', $attrs)) { HTMLDiffer::diffDebug("Image without a source\n"); parent::__construct($parent, '<' . $qName . '></' . $qName . '>'); } else { parent::__construct($parent, '<' . $qName . '>' . strtolower($attrs['src']) . '</' . $qName . '>'); } $this->qName = strtolower($qName); $this->attributes = $attrs; }
public function diffVersionsAction() { include_once 'DaisyDiff/HTMLDiff.php'; include_once 'simple_html_dom.php'; $versionFrom = Version::getById($this->_getParam("from")); $versionTo = Version::getById($this->_getParam("to")); $docFrom = $versionFrom->loadData(); $docTo = $versionTo->loadData(); // unlock the current session to access the version files session_write_close(); $request = $this->getRequest(); $fromSource = file_get_html($request->getScheme() . "://" . $request->getHttpHost() . $docFrom->getFullPath() . "?pimcore_version=" . $this->_getParam("from") . "&pimcore_admin_sid=" . $_COOKIE["pimcore_admin_sid"]); $toSource = file_get_html($request->getScheme() . "://" . $request->getHttpHost() . $docTo->getFullPath() . "?pimcore_version=" . $this->_getParam("to") . "&pimcore_admin_sid=" . $_COOKIE["pimcore_admin_sid"]); if ($docFrom instanceof Document_Page) { $from = $fromSource->find("body", 0); $to = $toSource->find("body", 0); } else { $from = $fromSource; $to = $toSource; } $diff = new HTMLDiffer(); $text = $diff->htmlDiff($from, $to); if ($docFrom instanceof Document_Page) { $fromSource->find("head", 0)->innertext = $fromSource->find("head", 0)->innertext . '<link rel="stylesheet" type="text/css" href="/pimcore/static/css/daisydiff.css" />'; $fromSource->find("body", 0)->innertext = $text; echo $fromSource; } else { echo '<link rel="stylesheet" type="text/css" href="/pimcore/static/css/daisydiff.css" />'; echo $text; } $this->removeViewRenderer(); }
function renderHtmlDiff() { global $wgOut, $wgTitle, $wgParser, $wgDebugComments; wfProfileIn(__METHOD__); $this->showDiffStyle(); $wgOut->addHTML('<h2>' . wfMsgHtml('visual-comparison') . "</h2>\n"); #add deleted rev tag if needed if (!$this->mNewRev->userCan(Revision::DELETED_TEXT)) { $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1</div>\n", 'rev-deleted-text-permission'); } else { if ($this->mNewRev->isDeleted(Revision::DELETED_TEXT)) { $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1</div>\n", 'rev-deleted-text-view'); } } if (!$this->mNewRev->isCurrent()) { $oldEditSectionSetting = $wgOut->parserOptions()->setEditSection(false); } $this->loadText(); // Old revision if (is_object($this->mOldRev)) { $wgOut->setRevisionId($this->mOldRev->getId()); } $popts = $wgOut->parserOptions(); $oldTidy = $popts->setTidy(true); $popts->setEditSection(false); $parserOutput = $wgParser->parse($this->mOldtext, $wgTitle, $popts, true, true, $wgOut->getRevisionId()); $popts->setTidy($oldTidy); //only for new? //$wgOut->addParserOutputNoText( $parserOutput ); $oldHtml = $parserOutput->getText(); wfRunHooks('OutputPageBeforeHTML', array(&$wgOut, &$oldHtml)); // New revision if (is_object($this->mNewRev)) { $wgOut->setRevisionId($this->mNewRev->getId()); } $popts = $wgOut->parserOptions(); $oldTidy = $popts->setTidy(true); $parserOutput = $wgParser->parse($this->mNewtext, $wgTitle, $popts, true, true, $wgOut->getRevisionId()); $popts->setTidy($oldTidy); $wgOut->addParserOutputNoText($parserOutput); $newHtml = $parserOutput->getText(); wfRunHooks('OutputPageBeforeHTML', array(&$wgOut, &$newHtml)); unset($parserOutput, $popts); $differ = new HTMLDiffer(new DelegatingContentHandler($wgOut)); $differ->htmlDiff($oldHtml, $newHtml); if ($wgDebugComments) { $wgOut->addHTML("\n<!-- HtmlDiff Debug Output:\n" . HTMLDiffer::getDebugOutput() . " End Debug -->"); } wfProfileOut(__METHOD__); }
// if already two revisions are selected, display diff // else display template with versions to select if ($args->doCompare) { // Side By Side $sbs = getItemsToCompare($args->left_item_id, $args->right_item_id, $gui->items); prepareUserFeedback($db, $gui, $args->req_spec_id, $labels, $sbs); $gui->attrDiff = getAttrDiff($sbs['left_item'], $sbs['right_item'], $labels); $cfields = getCFToCompare($sbs, $args->tproject_id, $itemMgr); $gui->cfieldsDiff = null; if (!is_null($cfields)) { $gui->cfieldsDiff = getCFDiff($cfields, $itemMgr); } $gui->diff = array("scope" => array()); foreach ($gui->diff as $key => $val) { if ($args->useDaisyDiff) { $diff = new HTMLDiffer(); list($differences, $diffcount) = $diff->htmlDiff($sbs['left_item'][$key], $sbs['right_item'][$key]); $gui->diff[$key]["diff"] = $differences; $gui->diff[$key]["count"] = $diffcount; } else { // insert line endings so diff is better readable and makes sense (not everything in one line) // then cast to array with \n as separating character, differ needs that $gui->diff[$key]["left"] = explode("\n", str_replace("</p>", "</p>\n", $sbs['left_item'][$key])); $gui->diff[$key]["right"] = explode("\n", str_replace("</p>", "</p>\n", $sbs['right_item'][$key])); $gui->diff[$key]["diff"] = $differ->inline($gui->diff[$key]["left"], $gui->leftID, $gui->diff[$key]["right"], $gui->rightID, $args->context); $gui->diff[$key]["count"] = count($differ->changes); } $gui->diff[$key]["heading"] = lang_get($key); // are there any changes? then display! if not, nothing to show here $additional = ''; $msg_key = "no_changes";
function __construct(TagNode $parent, $attrs) { if (!array_key_exists('src', $attrs)) { HTMLDiffer::diffDebug("Image without a source\n"); parent::__construct($parent, '<img></img>'); } else { parent::__construct($parent, '<img>' . strtolower($attrs['src']) . '</img>'); } $this->attributes = $attrs; }
<?php require_once 'Xml.php'; require_once 'Sanitizer.php'; require_once 'Diff.php'; require_once 'DifferenceEngine.php'; require_once 'Nodes.php'; require_once 'HTMLDiff.php'; function wfProfileIn($method) { } function wfProfileOut($method) { } class ContentHandler { var $output = ''; function addHtml($html) { $this->output .= $html; } } $from = getenv('from'); $to = getenv('to'); $handler = new ContentHandler(); $differ = new HTMLDiffer(new DelegatingContentHandler($handler)); $differ->htmlDiff($from, $to); echo $handler->output;
$steps = ""; $results = ""; foreach ($right['steps'] as $step) { $steps .= str_replace("</p>", "</p>\n", $step['actions']); $results .= str_replace("</p>", "</p>\n", $step['expected_results']); } $diff_array["steps"]["right"] = $steps; $diff_array["expected_results"]["right"] = $results; } foreach ($diff_array as $key => $val) { // 20110107 - new diff engine $localized_key = lang_get($key); $gui->diff[$key]["count"] = 0; if ($args->use_daisydiff) { // using daisydiff as diffing engine $diff = new HTMLDiffer(); list($differences, $diffcount) = $diff->htmlDiff($val['left'], $val['right']); $gui->diff[$key]["diff"] = $differences; $gui->diff[$key]["count"] = $diffcount; } else { // insert line endings so diff is better readable and makes sense (not everything in one line) // then cast to array with \n as separating character, differ needs that $gui->diff[$key]["left"] = explode("\n", str_replace("</p>", "</p>\n", $val['left'])); $gui->diff[$key]["right"] = explode("\n", str_replace("</p>", "</p>\n", $val['right'])); $gui->diff[$key]["diff"] = $differ->inline($gui->diff[$key]["left"], $gui->leftID, $gui->diff[$key]["right"], $gui->rightID, $args->context); $gui->diff[$key]["count"] = count($differ->changes); } $gui->diff[$key]["heading"] = $localized_key; //are there any changes? then display! if not, nothing to show here if ($gui->diff[$key]["count"] > 0) { $gui->diff[$key]["message"] = sprintf($labels["num_changes"], $localized_key, $diff_array[$key]["count"]);