protected function outputTag(Tag $tag)
	{
		$this->isRich = true;

		$tagName  = $tag->getName();
		$tagPos   = $tag->getPos();
		$tagLen   = $tag->getLen();
		$tagFlags = $tag->getFlags();

		if ($tagFlags & self::RULE_IGNORE_WHITESPACE)
		{
			$skipBefore = 1;
			$skipAfter  = ($tag->isEndTag()) ? 2 : 1;
		}
		else
		{
			$skipBefore = $skipAfter = 0;
		}

		// Current paragraph must end before the tag if:
		//  - the tag is a start (or self-closing) tag and it breaks paragraphs, or
		//  - the tag is an end tag (but not self-closing)
		$closeParagraph = false;
		if ($tag->isStartTag())
		{
			if ($tagFlags & self::RULE_BREAK_PARAGRAPH)
			{
				$closeParagraph = true;
			}
		}
		else
		{
			$closeParagraph = true;
		}

		// Let the cursor catch up with this tag's position
		$this->outputText($tagPos, $skipBefore, $closeParagraph);

		// Capture the text consumed by the tag
		$tagText = ($tagLen)
		         ? htmlspecialchars(substr($this->text, $tagPos, $tagLen), ENT_NOQUOTES, 'UTF-8')
		         : '';

		// Output current tag
		if ($tag->isStartTag())
		{
			// Handle paragraphs before opening the tag
			if (!($tagFlags & self::RULE_BREAK_PARAGRAPH))
			{
				$this->outputParagraphStart($tagPos);
			}

			// Record this tag's namespace, if applicable
			$colonPos = strpos($tagName, ':');
			if ($colonPos)
			{
				$this->namespaces[substr($tagName, 0, $colonPos)] = 0;
			}

			// Open the start tag and add its attributes, but don't close the tag
			$this->output .= '<' . $tagName;

			// We output the attributes in lexical order. Helps canonicalizing the output and could
			// prove useful someday
			$attributes = $tag->getAttributes();
			ksort($attributes);

			foreach ($attributes as $attrName => $attrValue)
			{
				$this->output .= ' ' . $attrName . '="' . str_replace("\n", '&#10;', htmlspecialchars($attrValue, ENT_COMPAT, 'UTF-8')) . '"';
			}

			if ($tag->isSelfClosingTag())
			{
				if ($tagLen)
				{
					$this->output .= '>' . $tagText . '</' . $tagName . '>';
				}
				else
				{
					$this->output .= '/>';
				}
			}
			elseif ($tagLen)
			{
				$this->output .= '><s>' . $tagText . '</s>';
			}
			else
			{
				$this->output .= '>';
			}
		}
		else
		{
			if ($tagLen)
			{
				$this->output .= '<e>' . $tagText . '</e>';
			}

			$this->output .= '</' . $tagName . '>';
		}

		// Move the cursor past the tag
		$this->pos = $tagPos + $tagLen;

		// Skip newlines (no other whitespace) after this tag
		$this->wsPos = $this->pos;
		while ($skipAfter && $this->wsPos < $this->textLen && $this->text[$this->wsPos] === "\n")
		{
			// Decrement the number of lines to skip
			--$skipAfter;

			// Move the cursor past the newline
			++$this->wsPos;
		}
	}
protected function outputTag(Tag $tag)
	{
		$this->isRich = true;

		$tagName  = $tag->getName();
		$tagPos   = $tag->getPos();
		$tagLen   = $tag->getLen();
		$tagFlags = $tag->getFlags();

		if ($tagFlags & self::RULE_IGNORE_WHITESPACE)
		{
			$skipBefore = 1;
			$skipAfter  = ($tag->isEndTag()) ? 2 : 1;
		}
		else
		{
			$skipBefore = $skipAfter = 0;
		}

		// Current paragraph must end before the tag if:
		//  - the tag is a start (or self-closing) tag and it breaks paragraphs, or
		//  - the tag is an end tag (but not self-closing)
		$closeParagraph = false;
		if ($tag->isStartTag())
		{
			if ($tagFlags & self::RULE_BREAK_PARAGRAPH)
			{
				$closeParagraph = true;
			}
		}
		else
		{
			$closeParagraph = true;
		}

		// Let the cursor catch up with this tag's position
		$this->outputText($tagPos, $skipBefore, $closeParagraph);

		// Capture the text consumed by the tag
		$tagText = ($tagLen)
		         ? htmlspecialchars(substr($this->text, $tagPos, $tagLen), ENT_NOQUOTES, 'UTF-8')
		         : '';

		// Output current tag
		if ($tag->isStartTag())
		{
			// Handle paragraphs before opening the tag
			if (!($tagFlags & self::RULE_BREAK_PARAGRAPH))
			{
				$this->outputParagraphStart($tagPos);
			}

			// Record this tag's namespace, if applicable
			$colonPos = strpos($tagName, ':');
			if ($colonPos)
			{
				$this->namespaces[substr($tagName, 0, $colonPos)] = 0;
			}

			// Open the start tag and add its attributes, but don't close the tag
			$this->output .= '<' . $tagName;

			// We output the attributes in lexical order. Helps canonicalizing the output and could
			// prove useful someday
			$attributes = $tag->getAttributes();
			ksort($attributes);

			foreach ($attributes as $attrName => $attrValue)
			{
				$this->output .= ' ' . $attrName . '="' . str_replace("\n", '&#10;', htmlspecialchars($attrValue, ENT_COMPAT, 'UTF-8')) . '"';
			}

			if ($tag->isSelfClosingTag())
			{
				if ($tagLen)
				{
					$this->output .= '>' . $tagText . '</' . $tagName . '>';
				}
				else
				{
					$this->output .= '/>';
				}
			}
			elseif ($tagLen)
			{
				$this->output .= '><s>' . $tagText . '</s>';
			}
			else
			{
				$this->output .= '>';
			}
		}
		else
		{
			if ($tagLen)
			{
				$this->output .= '<e>' . $tagText . '</e>';
			}

			$this->output .= '</' . $tagName . '>';
		}

		// Move the cursor past the tag
		$this->pos = $tagPos + $tagLen;

		// Skip newlines (no other whitespace) after this tag
		$this->wsPos = $this->pos;
		while ($skipAfter && $this->wsPos < $this->textLen && $this->text[$this->wsPos] === "\n")
		{
			// Decrement the number of lines to skip
			--$skipAfter;

			// Move the cursor past the newline
			++$this->wsPos;
		}
	}
protected function outputTag ( Tag $ tag ) { $ this -> isRich = true ; $ tagName = $ tag -> getName ( ) ; $ tagPos = $ tag -> getPos ( ) ; $ tagLen = $ tag -> getLen ( ) ; $ tagFlags = $ tag -> getFlags ( ) ; if ( $ tagFlags & self :: RULE_IGNORE_WHITESPACE ) { $ skipBefore = 1 ; $ skipAfter = ( $ tag -> isEndTag ( ) ) ? 2 : 1 ; } else { $ skipBefore = $ skipAfter = 0 ; } // Current paragraph must end before the tag if: //  - the tag is a start (or self-closing) tag and it breaks paragraphs, or //  - the tag is an end tag (but not self-closing) $ closeParagraph = false ; if ( $ tag -> isStartTag ( ) ) { if ( $ tagFlags & self :: RULE_BREAK_PARAGRAPH ) { $ closeParagraph = true ; } } else { $ closeParagraph = true ; } // Let the cursor catch up with this tag's position $ this -> outputText ( $ tagPos , $ skipBefore , $ closeParagraph ) ; // Capture the text consumed by the tag $ tagText = ( $ tagLen ) ? htmlspecialchars ( substr ( $ this -> text , $ tagPos , $ tagLen ) , ENT_NOQUOTES , 'UTF-8' ) : '' ; // Output current tag if ( $ tag -> isStartTag ( ) ) { // Handle paragraphs before opening the tag if ( ! ( $ tagFlags & self :: RULE_BREAK_PARAGRAPH ) ) { $ this -> outputParagraphStart ( $ tagPos ) ; } // Record this tag's namespace, if applicable $ colonPos = strpos ( $ tagName , ':' ) ; if ( $ colonPos ) { $ this -> namespaces [ substr ( $ tagName , 0 , $ colonPos ) ] = 0 ; } // Open the start tag and add its attributes, but don't close the tag $ this -> output .= '<' . $ tagName ; // We output the attributes in lexical order. Helps canonicalizing the output and could // prove useful someday $ attributes = $ tag -> getAttributes ( ) ; ksort ( $ attributes ) ; foreach ( $ attributes as $ attrName => $ attrValue ) { $ this -> output .= ' ' . $ attrName . '="' . str_replace ( "\n" , '&#10;' , htmlspecialchars ( $ attrValue , ENT_COMPAT , 'UTF-8' ) ) . '"' ; } if ( $ tag -> isSelfClosingTag ( ) ) { if ( $ tagLen ) { $ this -> output .= '>' . $ tagText . '</' . $ tagName . '>' ; } else { $ this -> output .= '/>' ; } } elseif ( $ tagLen ) { $ this -> output .= '><s>' . $ tagText . '</s>' ; } else { $ this -> output .= '>' ; } } else { if ( $ tagLen ) { $ this -> output .= '<e>' . $ tagText . '</e>' ; } $ this -> output .= '</' . $ tagName . '>' ; } // Move the cursor past the tag $ this -> pos = $ tagPos + $ tagLen ; // Skip newlines (no other whitespace) after this tag $ this -> wsPos = $ this -> pos ; while ( $ skipAfter && $ this -> wsPos < $ this -> textLen && $ this -> text [ $ this -> wsPos ] === "\n" ) { // Decrement the number of lines to skip -- $ skipAfter ; // Move the cursor past the newline ++ $ this -> wsPos ; } }
Append a tag to the output

@param  Tag  $tag Tag to append
@return void
Append a tag to the output