Ejemplo n.º 1
0
 /**
  * Returns element's start tag.
  * @return string
  */
 public function startTag()
 {
     if (!$this->name) {
         return '';
     }
     $s = '<' . $this->name;
     if (is_array($this->attrs)) {
         foreach ($this->attrs as $key => $value) {
             // skip NULLs and false boolean attributes
             if ($value === NULL || $value === FALSE) {
                 continue;
             }
             // true boolean attribute
             if ($value === TRUE) {
                 // in XHTML must use unminimized form
                 if (self::$xhtml) {
                     $s .= ' ' . $key . '="' . $key . '"';
                 } else {
                     $s .= ' ' . $key;
                 }
                 continue;
             } elseif (is_array($value)) {
                 // prepare into temporary array
                 $tmp = NULL;
                 foreach ($value as $k => $v) {
                     // skip NULLs & empty string; composite 'style' vs. 'others'
                     if ($v == NULL) {
                         continue;
                     } elseif (is_string($k)) {
                         $tmp[] = $k . ':' . $v;
                     } else {
                         $tmp[] = $v;
                     }
                 }
                 if (!$tmp) {
                     continue;
                 }
                 $value = implode($key === 'style' ? ';' : ' ', $tmp);
             } else {
                 $value = (string) $value;
             }
             // add new attribute
             $value = str_replace(array('&', '"', '<', '>', '@'), array('&amp;', '&quot;', '&lt;', '&gt;', '&#64;'), $value);
             $s .= ' ' . $key . '="' . Texy::freezeSpaces($value) . '"';
         }
     }
     // finish start tag
     if (self::$xhtml && $this->isEmpty) {
         return $s . ' />';
     }
     return $s . '>';
 }
Ejemplo n.º 2
0
 private function cb($matches)
 {
     list(, $mText, $mComment, $mEnd, $mTag, $mAttr, $mEmpty) = $matches;
     $s = '';
     if ($mText !== '') {
         $item = reset($this->tagStack);
         if ($item && !isset($item['dtdContent']['%DATA'])) {
         } elseif (!empty($this->tagUsed['pre']) || !empty($this->tagUsed['textarea']) || !empty($this->tagUsed['script'])) {
             $s = Texy::freezeSpaces($mText);
         } else {
             $s = preg_replace('#[ \\n]+#', ' ', $mText);
         }
     }
     if ($mComment) {
         return $s . '<' . Texy::freezeSpaces($mComment) . '>';
     }
     $mEmpty = $mEmpty || isset(TexyHtml::$emptyElements[$mTag]);
     if ($mEmpty && $mEnd) {
         return $s;
     }
     if ($mEnd) {
         if (empty($this->tagUsed[$mTag])) {
             return $s;
         }
         $tmp = array();
         $back = TRUE;
         foreach ($this->tagStack as $i => $item) {
             $tag = $item['tag'];
             $s .= $item['close'];
             $this->space -= $item['indent'];
             $this->tagUsed[$tag]--;
             $back = $back && isset(TexyHtml::$inlineElements[$tag]);
             unset($this->tagStack[$i]);
             if ($tag === $mTag) {
                 break;
             }
             array_unshift($tmp, $item);
         }
         if (!$back || !$tmp) {
             return $s;
         }
         $item = reset($this->tagStack);
         if ($item) {
             $dtdContent = $item['dtdContent'];
         } else {
             $dtdContent = $this->baseDTD;
         }
         if (!isset($dtdContent[$tmp[0]['tag']])) {
             return $s;
         }
         foreach ($tmp as $item) {
             $s .= $item['open'];
             $this->space += $item['indent'];
             $this->tagUsed[$item['tag']]++;
             array_unshift($this->tagStack, $item);
         }
     } else {
         $dtdContent = $this->baseDTD;
         if (!isset($this->texy->dtd[$mTag])) {
             $allowed = TRUE;
             $item = reset($this->tagStack);
             if ($item) {
                 $dtdContent = $item['dtdContent'];
             }
         } else {
             foreach ($this->tagStack as $i => $item) {
                 $dtdContent = $item['dtdContent'];
                 if (isset($dtdContent[$mTag])) {
                     break;
                 }
                 $tag = $item['tag'];
                 if ($item['close'] && (!isset(TexyHtml::$optionalEnds[$tag]) && !isset(TexyHtml::$inlineElements[$tag]))) {
                     break;
                 }
                 $s .= $item['close'];
                 $this->space -= $item['indent'];
                 $this->tagUsed[$tag]--;
                 unset($this->tagStack[$i]);
                 $dtdContent = $this->baseDTD;
             }
             $allowed = isset($dtdContent[$mTag]);
             if ($allowed && isset(TexyHtml::$prohibits[$mTag])) {
                 foreach (TexyHtml::$prohibits[$mTag] as $pTag) {
                     if (!empty($this->tagUsed[$pTag])) {
                         $allowed = FALSE;
                         break;
                     }
                 }
             }
         }
         if ($mEmpty) {
             if (!$allowed) {
                 return $s;
             }
             if ($this->xml) {
                 $mAttr .= " /";
             }
             $indent = $this->indent && empty($this->tagUsed['pre']) && empty($this->tagUsed['textarea']);
             if ($indent && $mTag === 'br') {
                 return rtrim($s) . '<' . $mTag . $mAttr . ">\n" . str_repeat("\t", max(0, $this->space - 1)) . "";
             }
             if ($indent && !isset(TexyHtml::$inlineElements[$mTag])) {
                 $space = "\r" . str_repeat("\t", $this->space);
                 return $s . $space . '<' . $mTag . $mAttr . '>' . $space;
             }
             return $s . '<' . $mTag . $mAttr . '>';
         }
         $open = NULL;
         $close = NULL;
         $indent = 0;
         if ($allowed) {
             $open = '<' . $mTag . $mAttr . '>';
             if (!empty($this->texy->dtd[$mTag][1])) {
                 $dtdContent = $this->texy->dtd[$mTag][1];
             }
             if ($this->indent && !isset(TexyHtml::$inlineElements[$mTag])) {
                 $close = "" . '</' . $mTag . '>' . "\n" . str_repeat("\t", $this->space);
                 $s .= "\n" . str_repeat("\t", $this->space++) . $open . "";
                 $indent = 1;
             } else {
                 $close = '</' . $mTag . '>';
                 $s .= $open;
             }
         }
         $item = array('tag' => $mTag, 'open' => $open, 'close' => $close, 'dtdContent' => $dtdContent, 'indent' => $indent);
         array_unshift($this->tagStack, $item);
         $tmp =& $this->tagUsed[$mTag];
         $tmp++;
     }
     return $s;
 }
Ejemplo n.º 3
0
 /**
  * Callback function: <tag> | </tag> | ....
  * @return string
  */
 private function cb($matches)
 {
     // html tag
     list(, $mText, $mComment, $mEnd, $mTag, $mAttr, $mEmpty) = $matches;
     //    [1] => text
     //    [1] => !-- comment --
     //    [2] => /
     //    [3] => TAG
     //    [4] => ... (attributes)
     //    [5] => /   (empty)
     $s = '';
     // phase #1 - stuff between tags
     if ($mText !== '') {
         $item = reset($this->tagStack);
         // text not allowed?
         if ($item && !isset($item['dtdContent']['%DATA'])) {
         } elseif (!empty($this->tagUsed['pre']) || !empty($this->tagUsed['textarea']) || !empty($this->tagUsed['script'])) {
             $s = Texy::freezeSpaces($mText);
         } else {
             $s = preg_replace('#[ \\n]+#', ' ', $mText);
         }
     }
     // phase #2 - HTML comment
     if ($mComment) {
         return $s . '<' . Texy::freezeSpaces($mComment) . '>';
     }
     // phase #3 - HTML tag
     $mEmpty = $mEmpty || isset(TexyHtml::$emptyElements[$mTag]);
     if ($mEmpty && $mEnd) {
         return $s;
     }
     // bad tag; /end/
     if ($mEnd) {
         // end tag
         // has start tag?
         if (empty($this->tagUsed[$mTag])) {
             return $s;
         }
         // autoclose tags
         $tmp = array();
         $back = TRUE;
         foreach ($this->tagStack as $i => $item) {
             $tag = $item['tag'];
             $s .= $item['close'];
             $this->space -= $item['indent'];
             $this->tagUsed[$tag]--;
             $back = $back && isset(TexyHtml::$inlineElements[$tag]);
             unset($this->tagStack[$i]);
             if ($tag === $mTag) {
                 break;
             }
             array_unshift($tmp, $item);
         }
         if (!$back || !$tmp) {
             return $s;
         }
         // allowed-check (nejspis neni ani potreba)
         $item = reset($this->tagStack);
         if ($item) {
             $dtdContent = $item['dtdContent'];
         } else {
             $dtdContent = $this->baseDTD;
         }
         if (!isset($dtdContent[$tmp[0]['tag']])) {
             return $s;
         }
         // autoopen tags
         foreach ($tmp as $item) {
             $s .= $item['open'];
             $this->space += $item['indent'];
             $this->tagUsed[$item['tag']]++;
             array_unshift($this->tagStack, $item);
         }
     } else {
         // start tag
         $dtdContent = $this->baseDTD;
         if (!isset($this->texy->dtd[$mTag])) {
             // unknown (non-html) tag
             $allowed = TRUE;
             $item = reset($this->tagStack);
             if ($item) {
                 $dtdContent = $item['dtdContent'];
             }
         } else {
             // optional end tag closing
             foreach ($this->tagStack as $i => $item) {
                 // is tag allowed here?
                 $dtdContent = $item['dtdContent'];
                 if (isset($dtdContent[$mTag])) {
                     break;
                 }
                 $tag = $item['tag'];
                 // auto-close hidden, optional and inline tags
                 if ($item['close'] && (!isset(TexyHtml::$optionalEnds[$tag]) && !isset(TexyHtml::$inlineElements[$tag]))) {
                     break;
                 }
                 // close it
                 $s .= $item['close'];
                 $this->space -= $item['indent'];
                 $this->tagUsed[$tag]--;
                 unset($this->tagStack[$i]);
                 $dtdContent = $this->baseDTD;
             }
             // is tag allowed in this content?
             $allowed = isset($dtdContent[$mTag]);
             // check deep element prohibitions
             if ($allowed && isset(TexyHtml::$prohibits[$mTag])) {
                 foreach (TexyHtml::$prohibits[$mTag] as $pTag) {
                     if (!empty($this->tagUsed[$pTag])) {
                         $allowed = FALSE;
                         break;
                     }
                 }
             }
         }
         // empty elements se neukladaji do zasobniku
         if ($mEmpty) {
             if (!$allowed) {
                 return $s;
             }
             if ($this->xml) {
                 $mAttr .= " /";
             }
             if ($this->indent && $mTag === 'br') {
                 // formatting exception
                 return rtrim($s) . '<' . $mTag . $mAttr . ">\n" . str_repeat("\t", max(0, $this->space - 1)) . "";
             }
             if ($this->indent && !isset(TexyHtml::$inlineElements[$mTag])) {
                 $space = "\r" . str_repeat("\t", $this->space);
                 return $s . $space . '<' . $mTag . $mAttr . '>' . $space;
             }
             return $s . '<' . $mTag . $mAttr . '>';
         }
         $open = NULL;
         $close = NULL;
         $indent = 0;
         /*
         if (!isset(TexyHtml::$inlineElements[$mTag])) {
         	// block tags always decorate with \n
         	$s .= "\n";
         	$close = "\n";
         }
         */
         if ($allowed) {
             $open = '<' . $mTag . $mAttr . '>';
             // receive new content (ins & del are special cases)
             if (!empty($this->texy->dtd[$mTag][1])) {
                 $dtdContent = $this->texy->dtd[$mTag][1];
             }
             // format output
             if ($this->indent && !isset(TexyHtml::$inlineElements[$mTag])) {
                 $close = "" . '</' . $mTag . '>' . "\n" . str_repeat("\t", $this->space);
                 $s .= "\n" . str_repeat("\t", $this->space++) . $open . "";
                 $indent = 1;
             } else {
                 $close = '</' . $mTag . '>';
                 $s .= $open;
             }
             // TODO: problematic formatting of select / options, object / params
         }
         // open tag, put to stack, increase counter
         $item = array('tag' => $mTag, 'open' => $open, 'close' => $close, 'dtdContent' => $dtdContent, 'indent' => $indent);
         array_unshift($this->tagStack, $item);
         $tmp =& $this->tagUsed[$mTag];
         $tmp++;
     }
     return $s;
 }