1 <?php 2 3 class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector 4 { 5 /** 6 * @type HTMLPurifier_Context 7 */ 8 private $context; 9 10 /** 11 * @type HTMLPurifier_Config 12 */ 13 private $config; 14 15 /** 16 * @type HTMLPurifier_AttrValidator 17 */ 18 private $attrValidator; 19 20 /** 21 * @type bool 22 */ 23 private $removeNbsp; 24 25 /** 26 * @type bool 27 */ 28 private $removeNbspExceptions; 29 30 /** 31 * Cached contents of %AutoFormat.RemoveEmpty.Predicate 32 * @type array 33 */ 34 private $exclude; 35 36 /** 37 * @param HTMLPurifier_Config $config 38 * @param HTMLPurifier_Context $context 39 * @return void 40 */ 41 public function prepare($config, $context) 42 { 43 parent::prepare($config, $context); 44 $this->config = $config; 45 $this->context = $context; 46 $this->removeNbsp = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp'); 47 $this->removeNbspExceptions = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions'); 48 $this->exclude = $config->get('AutoFormat.RemoveEmpty.Predicate'); 49 foreach ($this->exclude as $key => $attrs) { 50 if (!is_array($attrs)) { 51 // HACK, see HTMLPurifier/Printer/ConfigForm.php 52 $this->exclude[$key] = explode(';', $attrs); 53 } 54 } 55 $this->attrValidator = new HTMLPurifier_AttrValidator(); 56 } 57 58 /** 59 * @param HTMLPurifier_Token $token 60 */ 61 public function handleElement(&$token) 62 { 63 if (!$token instanceof HTMLPurifier_Token_Start) { 64 return; 65 } 66 $next = false; 67 $deleted = 1; // the current tag 68 for ($i = count($this->inputZipper->back) - 1; $i >= 0; $i--, $deleted++) { 69 $next = $this->inputZipper->back[$i]; 70 if ($next instanceof HTMLPurifier_Token_Text) { 71 if ($next->is_whitespace) { 72 continue; 73 } 74 if ($this->removeNbsp && !isset($this->removeNbspExceptions[$token->name])) { 75 $plain = str_replace("\xC2\xA0", "", $next->data); 76 $isWsOrNbsp = $plain === '' || ctype_space($plain); 77 if ($isWsOrNbsp) { 78 continue; 79 } 80 } 81 } 82 break; 83 } 84 if (!$next || ($next instanceof HTMLPurifier_Token_End && $next->name == $token->name)) { 85 $this->attrValidator->validateToken($token, $this->config, $this->context); 86 $token->armor['ValidateAttributes'] = true; 87 if (isset($this->exclude[$token->name])) { 88 $r = true; 89 foreach ($this->exclude[$token->name] as $elem) { 90 if (!isset($token->attr[$elem])) $r = false; 91 } 92 if ($r) return; 93 } 94 if (isset($token->attr['id']) || isset($token->attr['name'])) { 95 return; 96 } 97 $token = $deleted + 1; 98 for ($b = 0, $c = count($this->inputZipper->front); $b < $c; $b++) { 99 $prev = $this->inputZipper->front[$b]; 100 if ($prev instanceof HTMLPurifier_Token_Text && $prev->is_whitespace) { 101 continue; 102 } 103 break; 104 } 105 // This is safe because we removed the token that triggered this. 106 $this->rewindOffset($b+$deleted); 107 return; 108 } 109 } 110 } 111 112 // vim: et sw=4 sts=4
title
Description
Body
title
Description
Body
title
Description
Body
title
Body