function fix_newlines_for_clean_html($fixthistext)
{
$fixthistext_array = explode("\n", $fixthistext);
foreach ($fixthistext_array as $unfixedtextkey => $unfixedtextvalue)
{
//Makes sure empty lines are ignored
if (!preg_match("/^(\s)*$/", $unfixedtextvalue))
{
$fixedtextvalue = preg_replace("/>(\s|\t)*</U", ">\n<", $unfixedtextvalue);
$fixedtext_array[$unfixedtextkey] = $fixedtextvalue;
} else {
$fixedtext_array[$unfixedtextkey] = $unfixedtextvalue;
}
}
return implode("\n", $fixedtext_array);
}
function clean_html_code($uncleanhtml)
{
//Set wanted indentation
$indent = " ";
//Uses previous function to seperate tags
$fixed_uncleanhtml = fix_newlines_for_clean_html($uncleanhtml);
$uncleanhtml_array = explode("\n", $fixed_uncleanhtml);
//Sets no indentation
$indentlevel = 0;
foreach ($uncleanhtml_array as $uncleanhtml_key => $currentuncleanhtml)
{
//Removes all indentation
$currentuncleanhtml = preg_replace("/\t+/", "", $currentuncleanhtml);
$currentuncleanhtml = preg_replace("/^\s+/", "", $currentuncleanhtml);
$replaceindent = "";
//Sets the indentation from current indentlevel
for ($o = 0; $o < $indentlevel; $o++)
{
$replaceindent .= $indent;
}
//If self-closing tag, simply apply indent
if (preg_match("/<(.+)\/>/", $currentuncleanhtml))
{
$cleanhtml_array[$uncleanhtml_key] = $replaceindent.$currentuncleanhtml;
}
//If doctype declaration, or <html> tag, simply apply indent
else if (preg_match("/<!(.*)>/", $currentuncleanhtml) || preg_match("/<html(.*)>/", $currentuncleanhtml))
{
$cleanhtml_array[$uncleanhtml_key] = $replaceindent.$currentuncleanhtml;
}
//If opening AND closing tag on same line, simply apply indent
else if (preg_match("/<[^\/](.*)>/", $currentuncleanhtml) && preg_match("/<\/(.*)>/", $currentuncleanhtml))
{
$cleanhtml_array[$uncleanhtml_key] = $replaceindent.$currentuncleanhtml;
}
//If closing HTML tag or closing JavaScript clams, decrease indentation and then apply the new level
else if (preg_match("/<\/(.*)>/", $currentuncleanhtml) || preg_match("/^(\s|\t)*\}{1}(\s|\t)*$/", $currentuncleanhtml))
{
$indentlevel--;
$replaceindent = "";
for ($o = 0; $o < $indentlevel; $o++)
{
$replaceindent .= $indent;
}
$cleanhtml_array[$uncleanhtml_key] = $replaceindent.$currentuncleanhtml;
}
//If opening HTML tag AND not a stand-alone tag, or opening JavaScript clams, increase indentation and then apply new level
else if ((preg_match("/<[^\/](.*)>/", $currentuncleanhtml) && !preg_match("/<(link|meta|base|br|img|hr)(.*)>/", $currentuncleanhtml)) || preg_match("/^(\s|\t)*\{{1}(\s|\t)*$/", $currentuncleanhtml))
{
$cleanhtml_array[$uncleanhtml_key] = $replaceindent.$currentuncleanhtml;
$indentlevel++;
$replaceindent = "";
for ($o = 0; $o < $indentlevel; $o++)
{
$replaceindent .= $indent;
}
}
else
//Else, only apply indentation
{$cleanhtml_array[$uncleanhtml_key] = $replaceindent.$currentuncleanhtml;}
}
//Return single string seperated by newline
return implode("\n", $cleanhtml_array);
}
$modx->documentOutput = clean_html_code($modx->documentOutput);
return;
<div id="some-selector"></div>
<div id="some-selector> </div>
<a id="logo" href="./">
<img src="assets/images/logo.png" alt="Logo" />Site Name
</a>
<p>hello</p>
<a id="logo" href="./">
<img src="assets/images/logo.png" alt="Logo" />Site Name</a>
<p>hello</p>
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris nec sapien lacus. Sed interdum suscipit dapibus. Integer dictum ornare velit et posuere. Cras in metus risus. Mauris at vulputate lorem. Morbi gravida, nisl id viverra interdum, eros quam fringilla massa, vel rutrum justo sapien sed lectus. Etiam rutrum blandit commodo. Nullam ut sem a orci ullamcorper pretium. Aliquam et diam vitae risus varius imperdiet vel et tellus. Curabitur adipiscing eleifend ultrices. Vestibulum ultricies odio vestibulum massa malesuada id adipiscing magna lobortis. Proin bibendum ornare quam, molestie porta tellus molestie in. Nullam faucibus tortor vitae purus commodo ac posuere nisi posuere. Praesent mauris nulla, mattis nec viverra sed, dictum tempor augue.</p>
</div>
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris nec sapien lacus.
Sed interdum suscipit dapibus. Integer dictum ornare velit et posuere. Cras in metus risus.
Mauris at vulputate lorem. Morbi gravida, nisl id viverra interdum, eros quam fringilla
massa, vel rutrum justo sapien sed lectus. Etiam rutrum blandit commodo. Nullam ut sem
a orci ullamcorper pretium. Aliquam et diam vitae risus varius imperdiet vel et tellus.
Curabitur adipiscing eleifend ultrices. Vestibulum ultricies odio vestibulum massa
malesuada id adipiscing magna lobortis. Proin bibendum ornare quam, molestie porta
tellus molestie in. Nullam faucibus tortor vitae purus commodo ac posuere nisi posuere.
Praesent mauris nulla, mattis nec viverra sed, dictum tempor augue.</p>
</div>
<?php
function clean_xhtml($string, $keep_tags = null) {
if (!$keep_tags) {
$keep_regexp = '~<script[^>]*>.*?<\/script>|<pre[^>]*>.*?<\/pre>|<textarea[^>]*>.*?<\/textarea>~s';
}
// replace \r\n with \n
$string = preg_replace('~\r\n~ms', "\n", $string);
// replace \r with \n
$string = preg_replace('~\r~ms', "\n", $string);
// remove whitespace from the beginnig
$string = preg_replace('~^\s+~s', '', $string);
// remove whitespace from the end
$string = preg_replace('~\s+$~s', '', $string);
// store all tag which should remain the same
preg_match_all($keep_regexp, $string, $original_tags);
// remove whitespace from the beginning of each line
$string = preg_replace('~^\s+~m', '', $string);
// remove whitespace from the end of each line
$string = preg_replace('~\s+$~m', '', $string);
// removes empty lines
$string = preg_replace('~\n\s*(?=\n)~ms', '', $string);
// removes line breaks inside normal text
$string = preg_replace('~([^>\s])(\s\s+|\n)([^<\s])~m', '$1 $3', $string);
// correct indention
$indent = 0;
$string = explode("\n", $string);
foreach ($string as &$line) {
$correction = intval(substr($line, 0, 2) == '</'); // correct indention, if line starts with closing tag
$line = str_repeat("\t", $indent - $correction).$line;
$indent += substr_count($line, '<'); // indent every tag
$indent -= substr_count($line, '<!'); // subtract doctype declaration
$indent -= substr_count($line, '<?'); // subtract processing instructions
$indent -= substr_count($line, '/>'); // subtract self closing tags
$indent -= substr_count($line, '</') * 2; // subtract closing tags
}
$string = implode("\n", $string);
// fetch all tag which could been changed
preg_match_all($keep_regexp, $string, $current_tags);
// restore all stored tags
foreach ($current_tags[0] as $key => $match) {
$string = str_replace($match, $original_tags[0][$key], $string);
}
return $string;
}
$modx->documentOutput = clean_xhtml($modx->documentOutput);
return;
Nice.
You might consider using a property of the plugin to specify the indent string. That way users could choose to use spaces rather than a tab and choose how many spaces to indent.
[2011-09-27 16:10:24] (ERROR @ /home/neo/public_html/modx/core/cache/includes/elements/modplugin/5.include.cache.php : 46) PHP warning: preg_match_all(): Empty regular expression [2011-09-27 16:10:24] (ERROR @ /home/neo/public_html/modx/core/cache/includes/elements/modplugin/5.include.cache.php : 79) PHP warning: preg_match_all(): Empty regular expression [2011-09-27 16:10:24] (ERROR @ /home/neo/public_html/modx/core/cache/includes/elements/modplugin/5.include.cache.php : 80) PHP warning: Invalid argument supplied for foreach() [2011-09-27 16:13:46] (ERROR @ /home/neo/public_html/modx/core/cache/includes/elements/modplugin/5.include.cache.php : 46) PHP warning: preg_match_all(): Empty regular expression [2011-09-27 16:13:46] (ERROR @ /home/neo/public_html/modx/core/cache/includes/elements/modplugin/5.include.cache.php : 79) PHP warning: preg_match_all(): Empty regular expression [2011-09-27 16:13:46] (ERROR @ /home/neo/public_html/modx/core/cache/includes/elements/modplugin/5.include.cache.php : 80) PHP warning: Invalid argument supplied for foreach() [2011-09-27 16:17:01] (ERROR @ /home/neo/public_html/modx/core/cache/includes/elements/modplugin/5.include.cache.php : 46) PHP warning: preg_match_all(): Empty regular expression [2011-09-27 16:17:01] (ERROR @ /home/neo/public_html/modx/core/cache/includes/elements/modplugin/5.include.cache.php : 79) PHP warning: preg_match_all(): Empty regular expression [2011-09-27 16:17:01] (ERROR @ /home/neo/public_html/modx/core/cache/includes/elements/modplugin/5.include.cache.php : 80) PHP warning: Invalid argument supplied for foreach()
<?php
function clean_xhtml($string, $keep_tags = null) {
if (!$keep_tags) {
$keep_regexp = '~<script[^>]*>.*?<\/script>|<pre[^>]*>.*?<\/pre>|<textarea[^>]*>.*?<\/textarea>~s';
}
// replace \r\n with \n
$string = preg_replace('~\r\n~ms', "\n", $string);
// replace \r with \n
$string = preg_replace('~\r~ms', "\n", $string);
// remove whitespace from the beginnig
$string = preg_replace('~^\s+~s', '', $string);
// remove whitespace from the end
$string = preg_replace('~\s+$~s', '', $string);
// store all tag which should remain the same
preg_match_all($keep_regexp, $string, $original_tags);
// remove whitespace from the beginning of each line
$string = preg_replace('~^\s+~m', '', $string);
// remove whitespace from the end of each line
$string = preg_replace('~\s+$~m', '', $string);
// removes empty lines
$string = preg_replace('~\n\s*(?=\n)~ms', '', $string);
// removes line breaks inside normal text
$string = preg_replace('~([^>\s])(\s\s+|\n)([^<\s])~m', '$1 $3', $string);
// correct indention
$indent = 0;
$string = explode("\n", $string);
foreach ($string as &$line) {
$correction = intval(substr($line, 0, 2) == '</'); // correct indention, if line starts with closing tag
$line = str_repeat("\t", $indent - $correction) . $line;
$indent += substr_count($line, '<'); // indent every tag
$indent -= substr_count($line, '<!'); // subtract doctype declaration
$indent -= substr_count($line, '<?'); // subtract processing instructions
$indent -= substr_count($line, '/>'); // subtract self closing tags
$indent -= substr_count($line, '</') * 2; // subtract closing tags
}
$string = implode("\n", $string);
// fetch all tag which could been changed
preg_match_all($keep_regexp, $string, $current_tags);
// restore all stored tags
foreach ($current_tags[0] as $key => $match) {
$string = str_replace($match, $original_tags[0][$key], $string);
}
return $string;
}
$eventName = $modx->event->name;
switch ($eventName) {
case 'OnWebPageInit':
/* do something */
break;
case 'OnWebPagePrerender':
$content = $modx->resource->_output;
$content = clean_xhtml($content);
$modx->resource->_output = $content;
break;
}
return;