@param string $tag
@param array  $htmlOptions
@param string $content

@return string
163156
public static function createTag($tag, $htmlOptions = null, $content = null)
    {
        $return = '';
        $tag = self::clearAttributeKey(trim($tag));
        if ($tag) {
            $attributes = self::createAttributeString($htmlOptions);
            $return = '<' . $tag . (!empty($attributes) ? ' ' . $attributes : '');
            if ($content === false) {
                $return .= '>';
            } elseif ($content === true) {
                $return .= '>';
            } else {
                $return .= '>' . $content . self::createCloseTag($tag);
            }
        }

        return $return;
    }
696408
public static function pagination(array $items, $htmlOptions = array())
    {
        if (!empty($items)) {
            self::addCssClass('pagination', $htmlOptions);
            $size = TbArray::popValue('size', $htmlOptions);
            if (!empty($size)) {
                self::addCssClass('pagination-' . $size, $htmlOptions);
            }
            $align = TbArray::popValue('align', $htmlOptions);
            if (!empty($align)) {
                self::addCssClass('pagination-' . $align, $htmlOptions);
            }
            $listOptions = TbArray::popValue('listOptions', $htmlOptions, array());
            $output = self::openTag('div', $htmlOptions);
            $output .= self::openTag('ul', $listOptions);
            foreach ($items as $itemOptions) {
                // todo: consider removing the support for htmlOptions.
                $options = TbArray::popValue('htmlOptions', $itemOptions, array());
                if (!empty($options)) {
                    $itemOptions = TbArray::merge($options, $itemOptions);
                }
                $label = TbArray::popValue('label', $itemOptions, '');
                $url = TbArray::popValue('url', $itemOptions, false);
                $output .= self::paginationLink($label, $url, $itemOptions);
            }
            $output .= '</ul></div>';
            return $output;
        }
        return '';
    }
249802
public static function alert($color, $message, $htmlOptions = array())
    {
        self::addCssClass('alert', $htmlOptions);
        if (!empty($color)) {
            self::addCssClass('alert-' . $color, $htmlOptions);
        }
        if (TbArray::popValue('in', $htmlOptions, true)) {
            self::addCssClass('in', $htmlOptions);
        }
        if (TbArray::popValue('block', $htmlOptions, false)) {
            self::addCssClass('alert-block', $htmlOptions);
        }
        if (TbArray::popValue('fade', $htmlOptions, true)) {
            self::addCssClass('fade', $htmlOptions);
        }
        $closeText = TbArray::popValue('closeText', $htmlOptions, self::CLOSE_TEXT);
        $closeOptions = TbArray::popValue('closeOptions', $htmlOptions, array());
        $closeOptions['dismiss'] = self::CLOSE_DISMISS_ALERT;
        $output = self::openTag('div', $htmlOptions);
        $output .= $closeText !== false ? self::closeLink($closeText, '#', $closeOptions) : '';
        $output .= $message;
        $output .= '</div>';
        return $output;
    }
1360266
public static function formActions($actions, $htmlOptions = array())
    {
        self::addCssClass('form-actions', $htmlOptions);
        if (is_array($actions)) {
            $actions = implode(' ', $actions);
        }
        return self::tag('div', $htmlOptions, $actions);
    }
103183
public function createTag($tag, $attr = NULL, $content = NULL)
    {
        $temp = '<'.$tag;
        if($attr != NULL) {
            $attr = (array) $attr;
            foreach($attr as $key => $val) {
                if(is_numeric($key)) {
                    $val = strtolower(trim($val));
                    if(isset($this->attr[$tag][$val])) {
                        $args[$val] = $this->attr[$tag][$val];
                        //$args[] = $val.($this->attr[$tag][$val] == NULL ? '' : "=\"{$this->attr[$tag][$val]}\"");
                    }
                    else {
                        $args[$val] = NULL;
                    }
                }
                else {
                    if(!isset($args[$key])) {
                        $args[$key] = $val;
                    }
                }
                if(isset($this->attr[$tag][$key])) {
                    if(is_array($this->attr[$tag][$key])) {
                        foreach($this->attr[$tag][$key] as $k => $v) {
                            if(isset($v[$val]) && !isset($args[$val])) {
                                $args[$k] = $v[$val];
                            }
                        }
                    }
                    else {
                        if(!isset($args[$val])) {
                            $args[$key] = $this->attr[$tag][$key];
                        }
                    }
                }
            }
            unset($attr);
            foreach($args as $key => $val) {
                $attr[] = $key.($val == NULL ? '' : "=\"$val\"");
            }
            unset($args);
            $args = array_unique($attr);
            $args = implode(' ', $args);
        }
        $temp .= isset($args) ? ' '.$args.'>' : '>'; 
        if($content != NULL) {
            if(is_array($content)) {
                array_walk($content, function(&$val, $key) { $val = trim($val); } );//5.3
                $content = implode("\n",$content);
                $content = explode("\n", $content);
                $content = preg_replace('/^/', "\t", $content);
                #$content = preg_filter('/^/', "@", $content);
                $content = rtrim("\n".implode("\n", $content), "\n")."\n";
            }
            $temp .= $content;
        }
        if($this->tags[$tag] === true) {
            $temp .= '</'.$tag.'>';
        }
        return $temp;
    }
269236
protected static function inputAddOn($addOn, $htmlOptions)
    {
        $addOnOptions = TbArray::popValue('addOnOptions', $htmlOptions, array());
        self::addCssClass('add-on', $addOnOptions);
        return strpos($addOn, 'btn') === false // buttons should not be wrapped in a span
            ? self::tag('span', $addOnOptions, $addOn)
            : $addOn;
    }
105716
public static function media($image, $heading, $content, $htmlOptions = array())
    {
        $tag = TbArray::popValue('tag', $htmlOptions, 'div');
        self::addCssClass('media', $htmlOptions);
        $linkOptions = TbArray::popValue('linkOptions', $htmlOptions, array());
        TbArray::defaultValue('pull', self::PULL_LEFT, $linkOptions);
        $imageOptions = TbArray::popValue('imageOptions', $htmlOptions, array());
        self::addCssClass('media-object', $imageOptions);
        $contentOptions = TbArray::popValue('contentOptions', $htmlOptions, array());
        self::addCssClass('media-body', $contentOptions);
        $headingOptions = TbArray::popValue('headingOptions', $htmlOptions, array());
        self::addCssClass('media-heading', $headingOptions);
        $items = TbArray::popValue('items', $htmlOptions);

        $output = self::openTag($tag, $htmlOptions);
        $alt = TbArray::popValue('alt', $imageOptions, '');
        $href = TbArray::popValue('href', $linkOptions, '#');
        if (!empty($image)) {
            $output .= self::link(parent::image($image, $alt, $imageOptions), $href, $linkOptions);
        }
        $output .= self::openTag('div', $contentOptions);
        $output .= self::tag('h4', $headingOptions, $heading);
        $output .= $content;
        if (!empty($items)) {
            $output .= self::medias($items);
        }
        $output .= '</div>';
        $output .= self::closeTag($tag);
        return $output;
    }
1299581
public function parse(array $tag, $content) {
        $url = isset($tag['attributes']['href']) ? $tag['attributes']['href'] : $content;
        $protocols = $this->getConfig('protocols');
        $defaultProtocol = $this->getConfig('defaultProtocol');
        $hasProtocol = preg_match('/^(' . implode('|', $protocols) . ')/i', $url);

        if (!in_array($defaultProtocol, $protocols)) {
            $defaultProtocol = 'http';
        }

        // Allow relative and absolute paths, else check protocols
        if (!preg_match('/^(\.\.?)?\//', $url)) {
            if (!$hasProtocol) {
                // Only allow if no protocol exists, just not the ones not in the list
                if (preg_match('/^(?![a-z]+:\/\/)/', $url) && filter_var($defaultProtocol . '://' . $url, FILTER_VALIDATE_URL)) {
                    $url = $defaultProtocol . '://' . $url;
                } else {
                    return $url;
                }
            }

            // Return an invalid URL
            if (!filter_var($url, FILTER_VALIDATE_URL)) {
                return $url;
            }
        }

        $tag['attributes']['href'] = $url;

        if (!empty($tag['attributes']['target'])) {
            $tag['attributes']['target'] = '_' . $tag['attributes']['target'];
        }

        if ($this->getParser()->getConfig('shorthandLinks')) {
            $tag['content'] = $this->message('link');

            return '[' . parent::parse($tag, $content) . ']';
        }

        return parent::parse($tag, $content);
    }
497821
public static function modalBody($content, $htmlOptions = array())
    {
        self::addCssClass('modal-body', $htmlOptions);
        return self::tag('div', $htmlOptions, $content);
    }
169151
public function getHtmlOptions()
    {
        $r = '';
        if ($this->htmlClass) {
            $this->htmlOptions['class'] = (isset($this->htmlOptions['class']) ? $this->htmlOptions['class'] . ' ' : '') . $this->htmlClass;
        }
        foreach ($this->htmlOptions as $k => $v)
            $r .= "$k = '$v' ";
        return $r;
    }
298660
public function renderTag($tag)
    {
        $str = "<".$tag["tag"];
        foreach ($tag["options"] as $key=>$value) {
            $str.=" $key='$value'";
        }
        $str.=">".$tag["content"]."</".$tag["tag"].">";
        return $str;
    }
809475
public static function stripTagsAndAtts($content, $allowedTags = '', $allowedAtts = '')
    {
        if (isset($allowedTags) && is_array($allowedTags)) {
            $content = strip_tags($content, implode($allowedTags));
        } else {
            $content = strip_tags($content);
        }

        //Strip attributes
        $atts = \Municipio\Helper\Html::getHtmlAttributes($content);

        if ($atts && !empty($atts)) {
            if (isset($allowedAtts) && is_array($allowedAtts)) {
                foreach ($allowedAtts as $attribute) {
                    unset($atts[$attribute]);
                }
            }

            foreach ($atts as $att) {
                $content = str_replace($att, "", $content);
            }
        }

        return $content;
    }
131549
public function clientLink($client, $text = null, array $htmlOptions = [])
    {
        echo Html::beginTag('div',
            [
                'class' => $this->clientCssClass,
                'style' => 'float: left; padding-right: 20px;',
            ]);
        $text = Html::tag('span', $text, [
            'class' => 'auth-icon ' . $client->getName(),
            //'style' => 'padding-right: 50px;',
        ]);

        if (!array_key_exists('class', $htmlOptions)) {
            $htmlOptions['class'] = 'auth-link ' . $client->getName();
        }

        $viewOptions = $client->getViewOptions();
        if (empty($viewOptions['widget'])) {
            if ($this->popupMode) {
                if (isset($viewOptions['popupWidth'])) {
                    $htmlOptions['data-popup-width'] = $viewOptions['popupWidth'];
                }
                if (isset($viewOptions['popupHeight'])) {
                    $htmlOptions['data-popup-height'] = $viewOptions['popupHeight'];
                }
            }
            echo Html::a($text, $this->createClientUrl($client), $htmlOptions).'<br>';
        } else {
            $widgetConfig = $viewOptions['widget'];
            if (!isset($widgetConfig['class'])) {
                throw new InvalidConfigException('Widget config "class" parameter is missing');
            }
            /* @var $widgetClass Widget */
            $widgetClass = $widgetConfig['class'];
            if (!(is_subclass_of($widgetClass, AuthChoiceItem::className()))) {
                throw new InvalidConfigException('Item widget class must be subclass of "' . AuthChoiceItem::className() . '"');
            }
            unset($widgetConfig['class']);
            $widgetConfig['client'] = $client;
            $widgetConfig['authChoice'] = $this;
            echo $widgetClass::widget($widgetConfig);
        }
        echo Html::endTag('div');
    }
822358
protected static function generateTag($tag, $content, $attributes = [])
	{
		$text = '';
		$attribute = self::attribute($attributes);
		if (is_string($tag))
			$text .= "<{$tag}{$attribute}>".PHP_EOL;
		
		if (is_array($content)) {
			if (isset($content['type']) and $content['type'] = 'cdata') {
				$text .="<![CDATA[".PHP_EOL;
				$text .= $content['data'].PHP_EOL;
				$text .="]]>".PHP_EOL;
			} else {
				foreach ($content as $tg => $ct) {
					if (is_array($ct) && isset($ct['content']) && isset($ct['attribute']))
						$text .= self::generateTag($tg, $ct['content'], $ct['attribute']);
					else
						$text .= self::generateTag($tg, $ct);
				}
			}
		} elseif (is_string($content)) {
			$text .= $content;
		}
		
		if (is_string($tag))
			$text .= "</{$tag}>".PHP_EOL;
		return $text;
	}
704811
public function tagNotempty($tag, $content)
    {
        $name     = $tag['name'];
        $name     = $this->autoBuildVar($name);
        $parseStr = '<?php if(!(empty(' . $name . ') || ((' . $name . ' instanceof \think\Collection || ' . $name . ' instanceof \think\Paginator ) && ' . $name . '->isEmpty()))): ?>' . $content . '<?php endif; ?>';

        return $parseStr;
    }
1243784
public function javascriptTag($contentOrOptionWithBlock, $htmlOptions = null)
    {
        if ($contentOrOptionWithBlock instanceof \Closure) {
            ob_start();
            $contentOrOptionWithBlock();
            $contents = ob_get_clean();
            $htmlOptions = [];
        } elseif ($htmlOptions instanceof \Closure) {
            ob_start();
            $htmlOptions();
            $contents = ob_get_clean();
            $htmlOptions = $contentOrOptionWithBlock;
        } elseif (is_string($contentOrOptionWithBlock)) {
            $contents = $contentOrOptionWithBlock;
            if (!is_array($htmlOptions)) {
                $htmlOptions = [];
            }
        }
        
        return $this->contentTag('script', $contents, $htmlOptions);
    }
102079
public static function buttonGroup(array $buttons, $htmlOptions = array())
    {
        if (!empty($buttons)) {
            self::addCssClass('btn-group', $htmlOptions);
            if (TbArray::popValue('vertical', $htmlOptions, false)) {
                self::addCssClass('btn-group-vertical', $htmlOptions);
            }
            $toggle = TbArray::popValue('toggle', $htmlOptions);
            if (!empty($toggle)) {
                $htmlOptions['data-toggle'] = 'buttons-' . $toggle;
            }
            $parentOptions = array(
                'color' => TbArray::popValue('color', $htmlOptions),
                'size' => TbArray::popValue('size', $htmlOptions),
                'disabled' => TbArray::popValue('disabled', $htmlOptions)
            );
            $output = self::openTag('div', $htmlOptions);
            foreach ($buttons as $buttonOptions) {
                if (isset($buttonOptions['visible']) && $buttonOptions['visible'] === false) {
                    continue;
                }
                // todo: consider removing the support for htmlOptions.
                $options = TbArray::popValue('htmlOptions', $buttonOptions, array());
                if (!empty($options)) {
                    $buttonOptions = TbArray::merge($options, $buttonOptions);
                }
                $buttonLabel = TbArray::popValue('label', $buttonOptions, '');
                $buttonOptions = TbArray::copyValues(array('color', 'size', 'disabled'), $parentOptions, $buttonOptions);
                $items = TbArray::popValue('items', $buttonOptions, array());
                if (!empty($items)) {
                    $output .= self::buttonDropdown($buttonLabel, $items, $buttonOptions);
                } else {
					$type = TbArray::popValue('type', $buttonOptions, self::BUTTON_TYPE_LINKBUTTON);
					$output .= self::btn($type, $buttonLabel, $buttonOptions);
                }
            }
            $output .= '</div>';
            return $output;
        }
        return '';
    }