示例#1
1
/**
 * User handler for code block
 *
 * @param TexyHandlerInvocation  handler invocation
 * @param string  block type
 * @param string  text to highlight
 * @param string  language
 * @param TexyModifier modifier
 * @return TexyHtml
 */
function blockHandler($invocation, $blocktype, $content, $lang, $modifier)
{
    if ($blocktype !== 'block/code') {
        return $invocation->proceed();
    }
    $lang = strtoupper($lang);
    if ($lang == 'JAVASCRIPT') {
        $lang = 'JS';
    }
    $fshl = new fshlParser('HTML_UTF8', P_TAB_INDENT);
    if (!$fshl->isLanguage($lang)) {
        return $invocation->proceed();
    }
    $texy = $invocation->getTexy();
    $content = Texy::outdent($content);
    $content = $fshl->highlightString($lang, $content);
    $content = $texy->protect($content, Texy::CONTENT_BLOCK);
    $elPre = TexyHtml::el('pre');
    if ($modifier) {
        $modifier->decorate($texy, $elPre);
    }
    $elPre->attrs['class'] = strtolower($lang);
    $elCode = $elPre->create('code', $content);
    return $elPre;
}
 /**
  * Finish invocation.
  *
  * @param  TexyHandlerInvocation  handler invocation
  * @param  string
  * @param  TexyModifier
  *
  * @return TexyHtml
  */
 public function solve($invocation, $type, $modifier)
 {
     $el = TexyHtml::el('hr');
     $modifier->decorate($invocation->texy, $el);
     $class = $this->classes[$type[0]];
     if ($class && !isset($modifier->classes[$class])) {
         $el->attrs['class'][] = $class;
     }
     return $el;
 }
	/**
	 * Callback for:.
	 *
	 *   > They went in single file, running like hounds on a strong scent,
	 *   and an eager light was in their eyes. Nearly due west the broad
	 *   swath of the marching Orcs tramped its ugly slot; the sweet grass
	 *   of Rohan had been bruised and blackened as they passed.
	 *   >:http://www.mycom.com/tolkien/twotowers.html
	 *
	 * @param  TexyBlockParser
	 * @param  array      regexp matches
	 * @param  string     pattern name
	 * @return TexyHtml|string|FALSE
	 */
	public function pattern($parser, $matches)
	{
		list(, $mMod, $mPrefix, $mContent) = $matches;
		//    [1] => .(title)[class]{style}<>
		//    [2] => spaces |
		//    [3] => ... / LINK

		$tx = $this->texy;

		$el = TexyHtml::el('blockquote');
		$mod = new TexyModifier($mMod);
		$mod->decorate($tx, $el);

		$content = '';
		$spaces = '';
		do {
			if ($mPrefix === ':') {
				$mod->cite = $tx->blockQuoteModule->citeLink($mContent);
				$content .= "\n";
			} else {
				if ($spaces === '') $spaces = max(1, strlen($mPrefix));
				$content .= $mContent . "\n";
			}

			if (!$parser->next("#^>(?:|(\\ {1,$spaces}|:)(.*))()$#mA", $matches)) break;

/*
			if ($mPrefix === '>') {
				$content .= $mPrefix . $mContent . "\n";
			} elseif ($mPrefix === ':') {
				$mod->cite = $tx->blockQuoteModule->citeLink($mContent);
				$content .= "\n";
			} else {
				if ($spaces === '') $spaces = max(1, strlen($mPrefix));
				$content .= $mContent . "\n";
			}
			if (!$parser->next("#^\\>(?:(\\>|\\ {1,$spaces}|:)(.*))?()$#mA", $matches)) break;
*/

			list(, $mPrefix, $mContent) = $matches;
		} while (TRUE);

		$el->attrs['cite'] = $mod->cite;
		$el->parseBlock($tx, $content, $parser->isIndented());

		// no content?
		if (!$el->count()) return FALSE;

		// event listener
		$tx->invokeHandlers('afterBlockquote', array($parser, $el, $mod));

		return $el;
	}
/**
 * Pattern handler for PHP & JavaScript block syntaxes
 *
 * @param TexyBlockParser
 * @param array      regexp matches
 * @param string     pattern name
 * @return TexyHtml|string|FALSE
 */
function codeBlockHandler($parser, $matches, $name)
{
    list($content) = $matches;
    $lang = $name === 'phpBlockSyntax' ? 'PHP' : 'HTML';
    $fshl = new fshlParser('HTML_UTF8', P_TAB_INDENT);
    $texy = $parser->getTexy();
    $content = $fshl->highlightString($lang, $content);
    $content = $texy->protect($content, Texy::CONTENT_BLOCK);
    $elPre = TexyHtml::el('pre');
    $elPre->attrs['class'] = strtolower($lang);
    $elCode = $elPre->create('code', $content);
    return $elPre;
}
 /**
  * Finish invocation.
  *
  * @param  TexyHandlerInvocation  handler invocation
  * @param  string
  * @param  TexyModifier|NULL
  * @return TexyHtml|FALSE
  */
 public function solve($invocation, $content, $mod)
 {
     $tx = $this->texy;
     // find hard linebreaks
     if ($tx->mergeLines) {
         // ....
         // ... => \r means break line
         $content = TexyRegexp::replace($content, '#\\n +(?=\\S)#', "\r");
     } else {
         $content = TexyRegexp::replace($content, '#\\n#', "\r");
     }
     $el = TexyHtml::el('p');
     $el->parseLine($tx, $content);
     $content = $el->getText();
     // string
     // check content type
     // block contains block tag
     if (strpos($content, Texy::CONTENT_BLOCK) !== FALSE) {
         $el->setName(NULL);
         // ignores modifier!
         // block contains text (protected)
     } elseif (strpos($content, Texy::CONTENT_TEXTUAL) !== FALSE) {
         // leave element p
         // block contains text
     } elseif (preg_match('#[^\\s' . TexyPatterns::MARK . ']#u', $content)) {
         // leave element p
         // block contains only replaced element
     } elseif (strpos($content, Texy::CONTENT_REPLACED) !== FALSE) {
         $el->setName($tx->nontextParagraph);
         // block contains only markup tags or spaces or nothing
     } else {
         // if {ignoreEmptyStuff} return FALSE;
         if (!$mod) {
             $el->setName(NULL);
         }
     }
     if ($el->getName()) {
         // apply modifier
         if ($mod) {
             $mod->decorate($tx, $el);
         }
         // add <br />
         if (strpos($content, "\r") !== FALSE) {
             $key = $tx->protect('<br />', Texy::CONTENT_REPLACED);
             $content = str_replace("\r", $key, $content);
         }
     }
     $content = strtr($content, "\r\n", '  ');
     $el->setText($content);
     return $el;
 }
示例#6
0
文件: demo.php 项目: jiripudil/texy
/**
 * Pattern handler for block syntaxes
 *
 * @param TexyBlockParser
 * @param array      regexp matches
 * @param string     pattern name (myBlockSyntax1)
 * @return TexyHtml|string|FALSE
 */
function userBlockHandler($parser, $matches, $name)
{
    list(, $mTag, $mText) = $matches;
    $texy = $parser->getTexy();
    // create element
    if ($mTag === 'perex') {
        $el = TexyHtml::el('div');
        $el->attrs['class'][] = 'perex';
    } else {
        $el = TexyHtml::el($mTag);
    }
    // create content
    $el->parseLine($texy, $mText);
    return $el;
}
示例#7
0
/**
 * @param TexyHandlerInvocation  handler invocation
 * @param TexyImage
 * @param TexyLink
 * @param string
 * @param TexyModifier
 * @return TexyHtml|string|FALSE
 */
function figureHandler($invocation, $image, $link, $content, $modifier)
{
    // finish invocation by default way
    $el = $invocation->proceed();
    // change div -> dl
    $el->setName('dl');
    // change p -> dd
    $el[1]->setName('dd');
    // wrap img into dt
    $img = $el[0];
    unset($el[0]);
    $dt = TexyHtml::el('dt');
    $dt->add($img);
    $el->insert(0, $dt);
    return $el;
}
示例#8
0
function wiki_texy_InlineHandler($parser, $matches, $name)
{
    list(, $mContent, $mMod) = $matches;
    $texy = $parser->getTexy();
    $tag = 'a';
    $el = TexyHtml::el($tag);
    $mod = new TexyModifier($mMod);
    $mod->decorate($texy, $el);
    if ($name == 'wikilink') {
        $el->attrs['href'] = '?page=' . urlencode($mContent);
    } else {
        $el->attrs['href'] = $mContent;
    }
    $el->attrs['class'] = $name;
    $el->setText($mContent);
    $parser->again = TRUE;
    return $el;
}
示例#9
0
/**
 * User handler for unknown reference
 *
 * @param TexyHandlerInvocation  handler invocation
 * @param string   [refName]
 * @return TexyHtml|string
 */
function newReferenceHandler($parser, $refName)
{
    $names = array('Me', 'Punkrats', 'Servats', 'Bonifats');
    if (!isset($names[$refName])) {
        return FALSE;
    }
    // it's not my job
    $name = $names[$refName];
    $el = TexyHtml::el('a');
    $el->attrs['href'] = '#comm-' . $refName;
    // set link destination
    $el->attrs['class'][] = 'comment';
    // set class name
    $el->attrs['rel'] = 'nofollow';
    // enable rel="nofollow"
    $el->setText("[{$refName}] {$name}:");
    // set link label (with Texy formatting)
    return $el;
}
示例#10
0
 /**
  * Finish invocation.
  *
  * @param  TexyHandlerInvocation  handler invocation
  * @param  string
  * @param  string
  * @return TexyHtml|FALSE
  */
 public function solve($invocation, $emoticon, $raw)
 {
     $tx = $this->texy;
     $file = $this->icons[$emoticon];
     $el = TexyHtml::el('img');
     $el->attrs['src'] = Texy::prependRoot($file, $this->root === NULL ? $tx->imageModule->root : $this->root);
     $el->attrs['alt'] = $raw;
     $el->attrs['class'][] = $this->class;
     // file path
     $file = rtrim($this->fileRoot === NULL ? $tx->imageModule->fileRoot : $this->fileRoot, '/\\') . '/' . $file;
     if (@is_file($file)) {
         // intentionally @
         $size = @getImageSize($file);
         // intentionally @
         if (is_array($size)) {
             $el->attrs['width'] = $size[0];
             $el->attrs['height'] = $size[1];
         }
     }
     $tx->summary['images'][] = $el->attrs['src'];
     return $el;
 }
示例#11
0
 /**
  * User handler for code block.
  *
  * @param  TexyHandlerInvocation  handler invocation
  * @param  string  block type
  * @param  string  text to highlight
  * @param  string  language
  * @param  TexyModifier modifier
  * @return TexyHtml
  */
 public static function blockHandler($invocation, $blocktype, $content, $lang, $modifier)
 {
     if (preg_match('#^block/(php|neon|javascript|js|css|html|htmlcb|latte)$#', $blocktype)) {
         list(, $lang) = explode('/', $blocktype);
     } elseif ($blocktype !== 'block/code') {
         return $invocation->proceed();
     }
     $lang = strtolower($lang);
     if ($lang === 'htmlcb' || $lang === 'latte') {
         $lang = 'html';
     } elseif ($lang === 'javascript') {
         $lang = 'js';
     }
     if ($lang === 'html') {
         $langClass = 'FSHL\\Lexer\\LatteHtml';
     } elseif ($lang === 'js') {
         $langClass = 'FSHL\\Lexer\\LatteJavascript';
     } else {
         $langClass = 'FSHL\\Lexer\\' . ucfirst($lang);
     }
     $texy = $invocation->getTexy();
     $content = Texy::outdent($content);
     if (class_exists($langClass)) {
         $fshl = new FSHL\Highlighter(new FSHL\Output\Html(), FSHL\Highlighter::OPTION_TAB_INDENT);
         $content = $fshl->highlight($content, new $langClass());
     } else {
         $content = htmlSpecialChars($content);
     }
     $content = $texy->protect($content, Texy::CONTENT_BLOCK);
     $elPre = TexyHtml::el('pre');
     if ($modifier) {
         $modifier->decorate($texy, $elPre);
     }
     $elPre->attrs['class'] = 'src-' . strtolower($lang);
     $elCode = $elPre->create('code', $content);
     return $elPre;
 }
/**
 * User handler for code block
 *
 * @param TexyHandlerInvocation  handler invocation
 * @param string  block type
 * @param string  text to highlight
 * @param string  language
 * @param TexyModifier modifier
 * @return TexyHtml
 */
function blockHandler($invocation, $blocktype, $content, $lang, $modifier)
{
    if ($blocktype !== 'block/code') {
        return $invocation->proceed();
    }
    $texy = $invocation->getTexy();
    global $geshiPath;
    if ($lang == 'html') {
        $lang = 'html4strict';
    }
    $content = Texy::outdent($content);
    $geshi = new GeSHi($content, $lang, $geshiPath . 'geshi/');
    // GeSHi could not find the language
    if ($geshi->error) {
        return $invocation->proceed();
    }
    // do syntax-highlighting
    $geshi->set_encoding('UTF-8');
    $geshi->set_header_type(GESHI_HEADER_PRE);
    $geshi->enable_classes();
    $geshi->set_overall_style('color: #000066; border: 1px solid #d0d0d0; background-color: #f0f0f0;', true);
    $geshi->set_line_style('font: normal normal 95% \'Courier New\', Courier, monospace; color: #003030;', 'font-weight: bold; color: #006060;', true);
    $geshi->set_code_style('color: #000020;', 'color: #000020;');
    $geshi->set_link_styles(GESHI_LINK, 'color: #000060;');
    $geshi->set_link_styles(GESHI_HOVER, 'background-color: #f0f000;');
    // save generated stylesheet
    $texy->styleSheet .= $geshi->get_stylesheet();
    $content = $geshi->parse_code();
    // check buggy GESHI, it sometimes produce not UTF-8 valid code :-((
    $content = iconv('UTF-8', 'UTF-8//IGNORE', $content);
    // protect output is in HTML
    $content = $texy->protect($content, Texy::CONTENT_BLOCK);
    $el = TexyHtml::el();
    $el->setText($content);
    return $el;
}
 /**
  * Finish invocation.
  *
  * @param  TexyHandlerInvocation  handler invocation
  * @param  TexyLink
  * @param  TexyHtml|string
  * @return TexyHtml|string
  */
 public function solve($invocation, $link, $content = NULL)
 {
     if ($link->URL == NULL) {
         return $content;
     }
     $tx = $this->texy;
     $el = TexyHtml::el('a');
     if (empty($link->modifier)) {
         $nofollow = $popup = FALSE;
     } else {
         $nofollow = isset($link->modifier->classes['nofollow']);
         $popup = isset($link->modifier->classes['popup']);
         unset($link->modifier->classes['nofollow'], $link->modifier->classes['popup']);
         $el->attrs['href'] = NULL;
         // trick - move to front
         $link->modifier->decorate($tx, $el);
     }
     if ($link->type === TexyLink::IMAGE) {
         // image
         $el->attrs['href'] = Texy::prependRoot($link->URL, $tx->imageModule->linkedRoot);
         if ($this->imageClass) {
             $el->attrs['class'][] = $this->imageClass;
         } else {
             $el->attrs['onclick'] = $this->imageOnClick;
         }
     } else {
         $el->attrs['href'] = Texy::prependRoot($link->URL, $this->root);
         // rel="nofollow"
         if ($nofollow || $this->forceNoFollow && strpos($el->attrs['href'], '//') !== FALSE) {
             $el->attrs['rel'] = 'nofollow';
         }
     }
     // popup on click
     if ($popup) {
         $el->attrs['onclick'] = $this->popupOnClick;
     }
     if ($content !== NULL) {
         $el->add($content);
     }
     $tx->summary['links'][] = $el->attrs['href'];
     return $el;
 }
 /**
  * Callback for single list item.
  *
  * @param  TexyBlockParser
  * @param  string  bullet type
  * @param  string  left space
  * @param  string  html tag
  * @return TexyHtml|FALSE
  */
 public function patternItem($parser, $bullet, $indented, $tag)
 {
     $tx = $this->texy;
     $spacesBase = $indented ? '\\ {1,}' : '';
     $patternItem = "#^\n?({$spacesBase}){$bullet}\\ *(\\S.*)?" . TEXY_MODIFIER_H . "?()\$#mAUu";
     // first line with bullet
     $matches = NULL;
     if (!$parser->next($patternItem, $matches)) {
         return FALSE;
     }
     list(, $mIndent, $mContent, $mMod) = $matches;
     //    [1] => indent
     //    [2] => ...
     //    [3] => .(title)[class]{style}<>
     $elItem = TexyHtml::el($tag);
     $mod = new TexyModifier($mMod);
     $mod->decorate($tx, $elItem);
     // next lines
     $spaces = '';
     $content = ' ' . $mContent;
     // trick
     while ($parser->next('#^(\\n*)' . $mIndent . '(\\ {1,' . $spaces . '})(.*)()$#Am', $matches)) {
         list(, $mBlank, $mSpaces, $mContent) = $matches;
         //    [1] => blank line?
         //    [2] => spaces
         //    [3] => ...
         if ($spaces === '') {
             $spaces = strlen($mSpaces);
         }
         $content .= "\n" . $mBlank . $mContent;
     }
     // parse content
     $elItem->parseBlock($tx, $content, TRUE);
     if (isset($elItem[0]) && $elItem[0] instanceof TexyHtml) {
         $elItem[0]->setName(NULL);
     }
     return $elItem;
 }
示例#15
0
 static function texyBlockHandler($invocation, $blocktype, $content, $lang, $modifier)
 {
     if ($blocktype !== 'block/code') {
         return $invocation->proceed();
     }
     $texy = $invocation->getTexy();
     if ($lang == 'html') {
         $lang = 'html4strict';
     } elseif ($lang == 'yaml') {
         $lang = 'python';
     }
     $content = Texy::outdent($content);
     $geshi = new GeSHi($content, $lang);
     // GeSHi could not find the language
     if ($geshi->error) {
         return $invocation->proceed();
     }
     // do syntax-highlighting
     $geshi->set_encoding('UTF-8');
     $geshi->set_header_type(GESHI_HEADER_PRE);
     $geshi->enable_classes();
     $geshi->enable_keyword_links(false);
     $geshi->set_overall_style('');
     $geshi->set_overall_class('code');
     // save generated stylesheet
     $content = $geshi->parse_code();
     // check buggy GESHI, it sometimes produce not UTF-8 valid code :-((
     $content = iconv('UTF-8', 'UTF-8//IGNORE', $content);
     // protect output is in HTML
     $content = $texy->protect($content, Texy::CONTENT_BLOCK);
     $el = TexyHtml::el();
     $el->setText($content);
     return $el;
 }
示例#16
0
 /**
  * User handler for code block
  *
  * @param TexyHandlerInvocation  handler invocation
  * @param string  block type
  * @param string  text to highlight
  * @param string  language
  * @param TexyModifier modifier
  * @return TexyHtml
  */
 public function blockHandler($invocation, $blocktype, $content, $lang, $modifier)
 {
     /** @var \Texy $texy */
     $texy = $invocation->getTexy();
     $content = \Texy::outdent($content);
     $lexerData = $this->resolveLexer($blocktype);
     $lexer = $this->getLexerInstance($lexerData['name']);
     $highlighter = $this->getHighlighter($lexerData['countLines']);
     if ($lexer !== false) {
         $content = $highlighter->highlight($content, $lexer);
     } else {
         $content = htmlspecialchars($content);
     }
     $content = $texy->protect($content, \Texy::CONTENT_BLOCK);
     $elPre = \TexyHtml::el('pre');
     if ($modifier) {
         $modifier->decorate($texy, $elPre);
     }
     $elPre->attrs['class'] = mb_strtolower($this->getLanguage($blocktype));
     $elPre->create('code', $content);
     return $elPre;
 }
示例#17
0
 /**
  * Finish invocation.
  *
  * @param  TexyHandlerInvocation  handler invocation
  * @param  int  0..5
  * @param  string
  * @param  TexyModifier
  * @param  bool
  * @return TexyHtml
  */
 public function solve($invocation, $level, $content, $mod, $isSurrounded)
 {
     // as fixed balancing, for block/texysource & correct decorating
     $el = TexyHtml::el('h' . min(6, max(1, $level + $this->top)));
     $mod->decorate($this->texy, $el);
     $el->parseLine($this->texy, trim($content));
     $this->TOC[] = array('el' => $el, 'level' => $level, 'type' => $isSurrounded ? 'surrounded' : 'underlined');
     return $el;
 }
示例#18
0
 /**
  * Finish invocation.
  *
  * @param  TexyHandlerInvocation  handler invocation
  * @param  TexyImage
  * @param  TexyLink
  * @param  string
  * @param  TexyModifier
  * @return TexyHtml|FALSE
  */
 public function solve($invocation, TexyImage $image, $link, $content, $mod)
 {
     $tx = $this->texy;
     $hAlign = $image->modifier->hAlign;
     $image->modifier->hAlign = NULL;
     $elImg = $tx->imageModule->solve(NULL, $image, $link);
     // returns TexyHtml or false!
     if (!$elImg) {
         return FALSE;
     }
     $el = TexyHtml::el('div');
     if (!empty($image->width) && $this->widthDelta !== FALSE) {
         $el->attrs['style']['width'] = $image->width + $this->widthDelta . 'px';
     }
     $mod->decorate($tx, $el);
     $el[0] = $elImg;
     $el[1] = TexyHtml::el('p');
     $el[1]->parseLine($tx, ltrim($content));
     $class = $this->class;
     if ($hAlign) {
         $var = $hAlign . 'Class';
         // leftClass, rightClass
         if (!empty($this->{$var})) {
             $class = $this->{$var};
         } elseif (empty($tx->alignClasses[$hAlign])) {
             $el->attrs['style']['float'] = $hAlign;
         } else {
             $class .= '-' . $tx->alignClasses[$hAlign];
         }
     }
     $el->attrs['class'][] = $class;
     return $el;
 }
示例#19
0
 /**
  * Creates template.
  *
  * @param \ApiGen\Generator $generator
  */
 public function __construct(Generator $generator)
 {
     $this->generator = $generator;
     $this->config = $generator->getConfig();
     $that = $this;
     // Output in HTML5
     Nette\Utils\Html::$xhtml = false;
     // FSHL
     $fshl = new FSHL\Highlighter(new FSHL\Output\Html());
     $fshl->setLexer(new FSHL\Lexer\Php());
     // Texy
     $this->texy = new \Texy();
     $this->texy->allowedTags = array_flip($this->config->allowedHtml);
     $this->texy->allowed['list/definition'] = false;
     $this->texy->allowed['phrase/em-alt'] = false;
     $this->texy->allowed['longwords'] = false;
     $this->texy->allowed['typography'] = false;
     $this->texy->linkModule->shorten = false;
     // Highlighting <code>, <pre>
     $this->texy->addHandler('beforeParse', function ($texy, &$text, $singleLine) {
         $text = preg_replace('~<code>(.+?)</code>~', '#code#\\1#/code#', $text);
     });
     $this->texy->registerLinePattern(function ($parser, $matches, $name) use($fshl) {
         return \TexyHtml::el('code', $fshl->highlight($matches[1]));
     }, '~#code#(.+?)#/code#~', 'codeInlineSyntax');
     $this->texy->registerBlockPattern(function ($parser, $matches, $name) use($fshl) {
         if ('code' === $matches[1]) {
             $lines = array_filter(explode("\n", $matches[2]));
             if (!empty($lines)) {
                 $firstLine = array_shift($lines);
                 $indent = '';
                 $li = 0;
                 while (isset($firstLine[$li]) && preg_match('~\\s~', $firstLine[$li])) {
                     foreach ($lines as $line) {
                         if (!isset($line[$li]) || $firstLine[$li] !== $line[$li]) {
                             break 2;
                         }
                     }
                     $indent .= $firstLine[$li++];
                 }
                 if (!empty($indent)) {
                     $matches[2] = str_replace("\n" . $indent, "\n", 0 === strpos($matches[2], $indent) ? substr($matches[2], $li) : $matches[2]);
                 }
             }
             $content = $fshl->highlight($matches[2]);
         } else {
             $content = htmlspecialchars($matches[2]);
         }
         $content = $parser->getTexy()->protect($content, \Texy::CONTENT_BLOCK);
         return \TexyHtml::el('pre', $content);
     }, '~<(code|pre)>(.+?)</\\1>~s', 'codeBlockSyntax');
     // Common operations
     $this->registerHelperLoader('Nette\\Templating\\Helpers::loader');
     // PHP source highlight
     $this->registerHelper('highlightPHP', function ($source, $context) use($that, $fshl) {
         return $that->resolveLink($that->getTypeName($source), $context) ?: $fshl->highlight((string) $source);
     });
     $this->registerHelper('highlightValue', function ($definition, $context) use($that) {
         return $that->highlightPHP(preg_replace('~^(?:[ ]{4}|\\t)~m', '', $definition), $context);
     });
     // Urls
     $this->registerHelper('packageUrl', new Nette\Callback($this, 'getPackageUrl'));
     $this->registerHelper('namespaceUrl', new Nette\Callback($this, 'getNamespaceUrl'));
     $this->registerHelper('groupUrl', new Nette\Callback($this, 'getGroupUrl'));
     $this->registerHelper('classUrl', new Nette\Callback($this, 'getClassUrl'));
     $this->registerHelper('methodUrl', new Nette\Callback($this, 'getMethodUrl'));
     $this->registerHelper('propertyUrl', new Nette\Callback($this, 'getPropertyUrl'));
     $this->registerHelper('constantUrl', new Nette\Callback($this, 'getConstantUrl'));
     $this->registerHelper('functionUrl', new Nette\Callback($this, 'getFunctionUrl'));
     $this->registerHelper('elementUrl', new Nette\Callback($this, 'getElementUrl'));
     $this->registerHelper('sourceUrl', new Nette\Callback($this, 'getSourceUrl'));
     $this->registerHelper('manualUrl', new Nette\Callback($this, 'getManualUrl'));
     // Packages & namespaces
     $this->registerHelper('packageLinks', new Nette\Callback($this, 'getPackageLinks'));
     $this->registerHelper('namespaceLinks', new Nette\Callback($this, 'getNamespaceLinks'));
     $this->registerHelper('subgroupName', function ($groupName) {
         if ($pos = strrpos($groupName, '\\')) {
             return substr($groupName, $pos + 1);
         }
         return $groupName;
     });
     // Types
     $this->registerHelper('typeLinks', new Nette\Callback($this, 'getTypeLinks'));
     // Docblock descriptions
     $this->registerHelper('description', function ($annotation, $context) use($that) {
         $description = trim(strpbrk($annotation, "\n\r\t \$"));
         if ($context instanceof ReflectionParameter) {
             $description = preg_replace('~^(\\$' . $context->getName() . '(?:,\\.{3})?)(\\s+|$)~i', '\\2', $description, 1);
             $context = $context->getDeclaringFunction();
         }
         return $that->doc($description, $context);
     });
     $this->registerHelper('shortDescription', function ($element, $block = false) use($that) {
         return $that->doc($element->getShortDescription(), $element, $block);
     });
     $this->registerHelper('longDescription', function ($element) use($that) {
         $long = $element->getLongDescription();
         // Merge lines
         $long = preg_replace_callback('~(?:<(code|pre)>.+?</\\1>)|([^<]*)~s', function ($matches) {
             return !empty($matches[2]) ? preg_replace('~\\n(?:\\t|[ ])+~', ' ', $matches[2]) : $matches[0];
         }, $long);
         return $that->doc($long, $element, true);
     });
     // Individual annotations processing
     $this->registerHelper('annotation', function ($value, $name, $context) use($that, $generator) {
         switch ($name) {
             case 'param':
             case 'return':
             case 'throws':
                 $description = $that->description($value, $context);
                 return sprintf('<code>%s</code>%s', $that->getTypeLinks($value, $context), $description ? '<br>' . $description : '');
             case 'license':
                 list($url, $description) = $that->split($value);
                 return $that->link($url, $description ?: $url);
             case 'link':
                 list($url, $description) = $that->split($value);
                 if (Nette\Utils\Validators::isUrl($url)) {
                     return $that->link($url, $description ?: $url);
                 }
                 break;
             case 'see':
                 $doc = array();
                 foreach (preg_split('~\\s*,\\s*~', $value) as $link) {
                     if (null !== $generator->resolveElement($link, $context)) {
                         $doc[] = sprintf('<code>%s</code>', $that->getTypeLinks($link, $context));
                     } else {
                         $doc[] = $that->doc($link, $context);
                     }
                 }
                 return implode(', ', $doc);
             case 'uses':
             case 'usedby':
                 list($link, $description) = $that->split($value);
                 $separator = $context instanceof ReflectionClass || !$description ? ' ' : '<br>';
                 if (null !== $generator->resolveElement($link, $context)) {
                     return sprintf('<code>%s</code>%s%s', $that->getTypeLinks($link, $context), $separator, $description);
                 }
                 break;
             default:
                 break;
         }
         // Default
         return $that->doc($value, $context);
     });
     $todo = $this->config->todo;
     $internal = $this->config->internal;
     $this->registerHelper('annotationFilter', function (array $annotations, array $filter = array()) use($todo, $internal) {
         // Filtered, unsupported or deprecated annotations
         static $filtered = array('package', 'subpackage', 'property', 'property-read', 'property-write', 'method', 'abstract', 'access', 'final', 'filesource', 'global', 'name', 'static', 'staticvar');
         foreach ($filtered as $annotation) {
             unset($annotations[$annotation]);
         }
         // Custom filter
         foreach ($filter as $annotation) {
             unset($annotations[$annotation]);
         }
         // Show/hide internal
         if (!$internal) {
             unset($annotations['internal']);
         }
         // Show/hide tasks
         if (!$todo) {
             unset($annotations['todo']);
         }
         return $annotations;
     });
     $this->registerHelper('annotationSort', function (array $annotations) {
         uksort($annotations, function ($one, $two) {
             static $order = array('deprecated' => 0, 'category' => 1, 'copyright' => 2, 'license' => 3, 'author' => 4, 'version' => 5, 'since' => 6, 'see' => 7, 'uses' => 8, 'usedby' => 9, 'link' => 10, 'internal' => 11, 'example' => 12, 'tutorial' => 13, 'todo' => 14);
             if (isset($order[$one], $order[$two])) {
                 return $order[$one] - $order[$two];
             } elseif (isset($order[$one])) {
                 return -1;
             } elseif (isset($order[$two])) {
                 return 1;
             } else {
                 return strcasecmp($one, $two);
             }
         });
         return $annotations;
     });
     $this->registerHelper('annotationBeautify', function ($annotation) {
         static $names = array('usedby' => 'Used by');
         if (isset($names[$annotation])) {
             return $names[$annotation];
         }
         return Nette\Utils\Strings::firstUpper($annotation);
     });
     // Static files versioning
     $destination = $this->config->destination;
     $this->registerHelper('staticFile', function ($name) use($destination) {
         static $versions = array();
         $filename = $destination . DIRECTORY_SEPARATOR . $name;
         if (!isset($versions[$filename]) && is_file($filename)) {
             $versions[$filename] = sprintf('%u', crc32(file_get_contents($filename)));
         }
         if (isset($versions[$filename])) {
             $name .= '?' . $versions[$filename];
         }
         return $name;
     });
     // Source anchors
     $this->registerHelper('sourceAnchors', function ($source) {
         // Classes, interfaces, traits and exceptions
         $source = preg_replace_callback('~(<span\\s+class="php-keyword1">(?:class|interface|trait)</span>\\s+)(\\w+)~i', function ($matches) {
             $link = sprintf('<a id="%1$s" href="#%1$s">%1$s</a>', $matches[2]);
             return $matches[1] . $link;
         }, $source);
         // Methods and functions
         $source = preg_replace_callback('~(<span\\s+class="php-keyword1">function</span>\\s+)(\\w+)~i', function ($matches) {
             $link = sprintf('<a id="_%1$s" href="#_%1$s">%1$s</a>', $matches[2]);
             return $matches[1] . $link;
         }, $source);
         // Constants
         $source = preg_replace_callback('~(<span class="php-keyword1">const</span>)(.*?)(;)~is', function ($matches) {
             $links = preg_replace_callback('~(\\s|,)([A-Z_]+)(\\s+=)~', function ($matches) {
                 return $matches[1] . sprintf('<a id="%1$s" href="#%1$s">%1$s</a>', $matches[2]) . $matches[3];
             }, $matches[2]);
             return $matches[1] . $links . $matches[3];
         }, $source);
         // Properties
         $source = preg_replace_callback('~(<span\\s+class="php-keyword1">(?:private|protected|public|var|static)</span>\\s+)(<span\\s+class="php-var">.*?)(;)~is', function ($matches) {
             $links = preg_replace_callback('~(<span\\s+class="php-var">)(\\$\\w+)~i', function ($matches) {
                 return $matches[1] . sprintf('<a id="%1$s" href="#%1$s">%1$s</a>', $matches[2]);
             }, $matches[2]);
             return $matches[1] . $links . $matches[3];
         }, $source);
         return $source;
     });
     $this->registerHelper('urlize', array($this, 'urlize'));
     $this->registerHelper('relativePath', array($generator, 'getRelativePath'));
     $this->registerHelper('resolveElement', array($generator, 'resolveElement'));
     $this->registerHelper('getClass', array($generator, 'getClass'));
 }
示例#20
0
 /**
  * Finish invocation.
  *
  * @param  TexyHandlerInvocation  handler invocation
  * @param  string
  * @param  string
  * @param  TexyModifier
  * @param  TexyLink
  * @return TexyHtml
  */
 public function solve($invocation, $phrase, $content, $mod, $link)
 {
     $tx = $this->texy;
     $tag = isset($this->tags[$phrase]) ? $this->tags[$phrase] : NULL;
     if ($tag === 'a') {
         $tag = $link && $this->linksAllowed ? NULL : 'span';
     }
     if ($phrase === 'phrase/code') {
         $content = $tx->protect(Texy::escapeHtml($content), Texy::CONTENT_TEXTUAL);
     }
     if ($phrase === 'phrase/strong+em') {
         $el = TexyHtml::el($this->tags['phrase/strong']);
         $el->create($this->tags['phrase/em'], $content);
         $mod->decorate($tx, $el);
     } elseif ($tag) {
         $el = TexyHtml::el($tag)->setText($content);
         $mod->decorate($tx, $el);
         if ($tag === 'q') {
             $el->attrs['cite'] = $mod->cite;
         }
     } else {
         $el = $content;
         // trick
     }
     if ($link && $this->linksAllowed) {
         return $tx->linkModule->solve(NULL, $link, $el);
     }
     return $el;
 }
示例#21
0
 function patternTable($parser, $matches)
 {
     list(, $mMod) = $matches;
     $tx = $this->texy;
     $el = TexyHtml::el('table');
     $mod = new TexyModifier($mMod);
     $mod->decorate($tx, $el);
     $parser->moveBackward();
     if ($parser->next('#^\\|(\\#|\\=){2,}(?!\\1)(.*)\\1*\\|? *' . TEXY_MODIFIER_H . '?()$#Um', $matches)) {
         list(, , $mContent, $mMod) = $matches;
         $caption = $el->create('caption');
         $mod = new TexyModifier($mMod);
         $mod->decorate($tx, $caption);
         $caption->parseLine($tx, $mContent);
     }
     $isHead = FALSE;
     $colModifier = array();
     $prevRow = array();
     $rowCounter = 0;
     $colCounter = 0;
     $elPart = NULL;
     while (TRUE) {
         if ($parser->next('#^\\|[+-]{3,}$#Um', $matches)) {
             $isHead = !$isHead;
             $prevRow = array();
             continue;
         }
         if ($parser->next('#^\\|(.*)(?:|\\|\\ *' . TEXY_MODIFIER_HV . '?)()$#U', $matches)) {
             if ($rowCounter === 0 && !$isHead && $parser->next('#^\\|[+-]{3,}$#Um', $foo)) {
                 $isHead = TRUE;
                 $parser->moveBackward();
             }
             if ($elPart === NULL) {
                 $elPart = $el->create($isHead ? 'thead' : 'tbody');
             } elseif (!$isHead && $elPart->getName() === 'thead') {
                 $this->finishPart($elPart);
                 $elPart = $el->create('tbody');
             }
             list(, $mContent, $mMod) = $matches;
             $elRow = TexyHtml::el('tr');
             $mod = new TexyModifier($mMod);
             $mod->decorate($tx, $elRow);
             $rowClass = $rowCounter % 2 === 0 ? $this->oddClass : $this->evenClass;
             if ($rowClass && !isset($mod->classes[$this->oddClass]) && !isset($mod->classes[$this->evenClass])) {
                 $elRow->attrs['class'][] = $rowClass;
             }
             $col = 0;
             $elCell = NULL;
             $mContent = str_replace('\\|', '&#x7C;', $mContent);
             foreach (explode('|', $mContent) as $cell) {
                 if ($cell === '' && $elCell) {
                     $elCell->colSpan++;
                     unset($prevRow[$col]);
                     $col++;
                     continue;
                 }
                 if (isset($prevRow[$col]) && preg_match('#\\^\\ *$|\\*??(.*)\\ +\\^$#AU', $cell, $matches)) {
                     $prevRow[$col]->rowSpan++;
                     $matches[] = '';
                     $prevRow[$col]->text .= "\n" . $matches[1];
                     $col += $prevRow[$col]->colSpan;
                     $elCell = NULL;
                     continue;
                 }
                 if (!preg_match('#(\\*??)\\ *' . TEXY_MODIFIER_HV . '??(.*)' . TEXY_MODIFIER_HV . '?\\ *()$#AU', $cell, $matches)) {
                     continue;
                 }
                 list(, $mHead, $mModCol, $mContent, $mMod) = $matches;
                 if ($mModCol) {
                     $colModifier[$col] = new TexyModifier($mModCol);
                 }
                 if (isset($colModifier[$col])) {
                     $mod = clone $colModifier[$col];
                 } else {
                     $mod = new TexyModifier();
                 }
                 $mod->setProperties($mMod);
                 $elCell = new TexyTableCellElement();
                 $elCell->setName($isHead || $mHead === '*' ? 'th' : 'td');
                 $mod->decorate($tx, $elCell);
                 $elCell->text = $mContent;
                 $elRow->add($elCell);
                 $prevRow[$col] = $elCell;
                 $col++;
             }
             while ($col < $colCounter) {
                 $elCell = new TexyTableCellElement();
                 $elCell->setName($isHead ? 'th' : 'td');
                 if (isset($colModifier[$col])) {
                     $colModifier[$col]->decorate($tx, $elCell);
                 }
                 $elRow->add($elCell);
                 $prevRow[$col] = $elCell;
                 $col++;
             }
             $colCounter = $col;
             if ($elRow->count()) {
                 $elPart->add($elRow);
                 $rowCounter++;
             } else {
                 foreach ($prevRow as $elCell) {
                     $elCell->rowSpan--;
                 }
             }
             continue;
         }
         break;
     }
     if ($elPart === NULL) {
         return FALSE;
     }
     if ($elPart->getName() === 'thead') {
         $elPart->setName('tbody');
     }
     $this->finishPart($elPart);
     $tx->invokeHandlers('afterTable', array($parser, $el, $mod));
     return $el;
 }
 /**
  * Callback for:.
  *
  *  Term: .(title)[class]{style}>
  *    - description 1
  *    - description 2
  *    - description 3
  *
  * @param  TexyBlockParser
  * @param  array      regexp matches
  * @param  string     pattern name
  *
  * @return TexyHtml
  */
 public function patternDefList($parser, $matches)
 {
     list(, $mMod, , , , $mBullet) = $matches;
     //   [1] => .(title)[class]{style}<>
     //   [2] => ...
     //   [3] => .(title)[class]{style}<>
     //   [4] => space
     //   [5] => - * +
     $tx = $this->texy;
     $bullet = null;
     foreach ($this->bullets as $desc) {
         if (preg_match('#' . $desc[0] . '#Au', $mBullet)) {
             $bullet = isset($desc[3]) ? $desc[3] : $desc[0];
             break;
         }
     }
     $el = TexyHtml::el('dl');
     $mod = new TexyModifier($mMod);
     $mod->decorate($tx, $el);
     $parser->moveBackward(2);
     $patternTerm = '#^\\n?(\\S.*)\\:\\ *' . TEXY_MODIFIER_H . '?()$#mUA';
     while (true) {
         if ($elItem = $this->patternItem($parser, $bullet, true, 'dd')) {
             $el->add($elItem);
             continue;
         }
         if ($parser->next($patternTerm, $matches)) {
             list(, $mContent, $mMod) = $matches;
             //    [1] => ...
             //    [2] => .(title)[class]{style}<>
             $elItem = TexyHtml::el('dt');
             $modItem = new TexyModifier($mMod);
             $modItem->decorate($tx, $elItem);
             $elItem->parseLine($tx, $mContent);
             $el->add($elItem);
             continue;
         }
         break;
     }
     // event listener
     $tx->invokeHandlers('afterDefinitionList', array($parser, $el, $mod));
     return $el;
 }
示例#23
0
 /**
  * Finish invocation.
  *
  * @param  TexyHandlerInvocation  handler invocation
  * @param  TexyHtml  element
  * @param  bool      is start tag?
  * @param  bool      is empty?
  * @return TexyHtml|string|FALSE
  */
 public function solveTag($invocation, TexyHtml $el, $isStart, $forceEmpty = NULL)
 {
     $tx = $this->texy;
     // tag & attibutes
     $allowedTags = $tx->allowedTags;
     // speed-up
     if (!$allowedTags) {
         return FALSE;
     }
     // all tags are disabled
     // convert case
     $name = $el->getName();
     $lower = strtolower($name);
     if (isset($tx->dtd[$lower]) || $name === strtoupper($name)) {
         // complete UPPER convert to lower
         $name = $lower;
         $el->setName($name);
     }
     if (is_array($allowedTags)) {
         if (!isset($allowedTags[$name])) {
             return FALSE;
         }
         $allowedAttrs = $allowedTags[$name];
         // allowed attrs
     } else {
         // allowedTags === Texy::ALL
         if ($forceEmpty) {
             $el->setName($name, TRUE);
         }
         $allowedAttrs = Texy::ALL;
         // all attrs are allowed
     }
     // end tag? we are finished
     if (!$isStart) {
         return $el;
     }
     $elAttrs =& $el->attrs;
     // process attributes
     if (!$allowedAttrs) {
         $elAttrs = array();
     } elseif (is_array($allowedAttrs)) {
         // skip disabled
         $allowedAttrs = array_flip($allowedAttrs);
         foreach ($elAttrs as $key => $foo) {
             if (!isset($allowedAttrs[$key])) {
                 unset($elAttrs[$key]);
             }
         }
     }
     // apply allowedClasses
     $tmp = $tx->_classes;
     // speed-up
     if (isset($elAttrs['class'])) {
         if (is_array($tmp)) {
             $elAttrs['class'] = explode(' ', $elAttrs['class']);
             foreach ($elAttrs['class'] as $key => $value) {
                 if (!isset($tmp[$value])) {
                     unset($elAttrs['class'][$key]);
                 }
             }
             // id & class are case-sensitive
         } elseif ($tmp !== Texy::ALL) {
             $elAttrs['class'] = NULL;
         }
     }
     // apply allowedClasses for ID
     if (isset($elAttrs['id'])) {
         if (is_array($tmp)) {
             if (!isset($tmp['#' . $elAttrs['id']])) {
                 $elAttrs['id'] = NULL;
             }
         } elseif ($tmp !== Texy::ALL) {
             $elAttrs['id'] = NULL;
         }
     }
     // apply allowedStyles
     if (isset($elAttrs['style'])) {
         $tmp = $tx->_styles;
         // speed-up
         if (is_array($tmp)) {
             $styles = explode(';', $elAttrs['style']);
             $elAttrs['style'] = NULL;
             foreach ($styles as $value) {
                 $pair = explode(':', $value, 2);
                 $prop = trim($pair[0]);
                 if (isset($pair[1]) && isset($tmp[strtolower($prop)])) {
                     // CSS is case-insensitive
                     $elAttrs['style'][$prop] = $pair[1];
                 }
             }
         } elseif ($tmp !== Texy::ALL) {
             $elAttrs['style'] = NULL;
         }
     }
     if ($name === 'img') {
         if (!isset($elAttrs['src'])) {
             return FALSE;
         }
         if (!$tx->checkURL($elAttrs['src'], Texy::FILTER_IMAGE)) {
             return FALSE;
         }
         $tx->summary['images'][] = $elAttrs['src'];
     } elseif ($name === 'a') {
         if (!isset($elAttrs['href']) && !isset($elAttrs['name']) && !isset($elAttrs['id'])) {
             return FALSE;
         }
         if (isset($elAttrs['href'])) {
             if ($tx->linkModule->forceNoFollow && strpos($elAttrs['href'], '//') !== FALSE) {
                 if (isset($elAttrs['rel'])) {
                     $elAttrs['rel'] = (array) $elAttrs['rel'];
                 }
                 $elAttrs['rel'][] = 'nofollow';
             }
             if (!$tx->checkURL($elAttrs['href'], Texy::FILTER_ANCHOR)) {
                 return FALSE;
             }
             $tx->summary['links'][] = $elAttrs['href'];
         }
     } elseif (preg_match('#^h[1-6]#i', $name)) {
         $tx->headingModule->TOC[] = array('el' => $el, 'level' => (int) substr($name, 1), 'type' => 'html');
     }
     $el->validateAttrs($tx->dtd);
     return $el;
 }
 /**
  * Callback for:.
  *
  *  .(title)[class]{style}>
  *  |------------------
  *  | xxx | xxx | xxx | .(..){..}[..]
  *  |------------------
  *  | aa  | bb  | cc  |
  *
  * @param  TexyBlockParser
  * @param  array      regexp matches
  * @param  string     pattern name
  * @return TexyHtml|string|FALSE
  */
 public function patternTable($parser, $matches)
 {
     list(, $mMod) = $matches;
     //    [1] => .(title)[class]{style}<>_
     $tx = $this->texy;
     $el = TexyHtml::el('table');
     $mod = new TexyModifier($mMod);
     $mod->decorate($tx, $el);
     $parser->moveBackward();
     if ($parser->next('#^\\|(\\#|\\=){2,}(?![|\\#=+])(.+)\\1*\\|? *' . TEXY_MODIFIER_H . '?()$#Um', $matches)) {
         list(, , $mContent, $mMod) = $matches;
         //    [1] => # / =
         //    [2] => ....
         //    [3] => .(title)[class]{style}<>
         $caption = $el->create('caption');
         $mod = new TexyModifier($mMod);
         $mod->decorate($tx, $caption);
         $caption->parseLine($tx, $mContent);
     }
     $isHead = FALSE;
     $colModifier = array();
     $prevRow = array();
     // rowSpan building helper
     $rowCounter = 0;
     $colCounter = 0;
     $elPart = NULL;
     $lineMode = FALSE;
     // rows must be separated by lines
     while (TRUE) {
         if ($parser->next('#^\\|([=-])[+|=-]{2,}$#Um', $matches)) {
             // line
             if ($lineMode) {
                 if ($matches[1] === '=') {
                     $isHead = !$isHead;
                 }
             } else {
                 $isHead = !$isHead;
                 $lineMode = $matches[1] === '=';
             }
             $prevRow = array();
             continue;
         }
         if ($parser->next('#^\\|(.*)(?:|\\|\\ *' . TEXY_MODIFIER_HV . '?)()$#U', $matches)) {
             // smarter head detection
             if ($rowCounter === 0 && !$isHead && $parser->next('#^\\|[=-][+|=-]{2,}$#Um', $foo)) {
                 $isHead = TRUE;
                 $parser->moveBackward();
             }
             if ($elPart === NULL) {
                 $elPart = $el->create($isHead ? 'thead' : 'tbody');
             } elseif (!$isHead && $elPart->getName() === 'thead') {
                 $this->finishPart($elPart);
                 $elPart = $el->create('tbody');
             }
             // PARSE ROW
             list(, $mContent, $mMod) = $matches;
             //    [1] => ....
             //    [2] => .(title)[class]{style}<>_
             $elRow = TexyHtml::el('tr');
             $mod = new TexyModifier($mMod);
             $mod->decorate($tx, $elRow);
             $rowClass = $rowCounter % 2 === 0 ? $this->oddClass : $this->evenClass;
             if ($rowClass && !isset($mod->classes[$this->oddClass]) && !isset($mod->classes[$this->evenClass])) {
                 $elRow->attrs['class'][] = $rowClass;
             }
             $col = 0;
             $elCell = NULL;
             // special escape sequence \|
             $mContent = str_replace('\\|', '&#x7C;', $mContent);
             foreach (explode('|', $mContent) as $cell) {
                 // rowSpan
                 if (isset($prevRow[$col]) && ($lineMode || preg_match('#\\^\\ *$|\\*??(.*)\\ +\\^$#AU', $cell, $matches))) {
                     $prevRow[$col]->rowSpan++;
                     if (!$lineMode) {
                         $cell = isset($matches[1]) ? $matches[1] : '';
                     }
                     $prevRow[$col]->text .= "\n" . $cell;
                     $col += $prevRow[$col]->colSpan;
                     $elCell = NULL;
                     continue;
                 }
                 // colSpan
                 if ($cell === '' && $elCell) {
                     $elCell->colSpan++;
                     unset($prevRow[$col]);
                     $col++;
                     continue;
                 }
                 // common cell
                 if (!preg_match('#(\\*??)\\ *' . TEXY_MODIFIER_HV . '??(.*)' . TEXY_MODIFIER_HV . '?\\ *()$#AU', $cell, $matches)) {
                     continue;
                 }
                 list(, $mHead, $mModCol, $mContent, $mMod) = $matches;
                 //    [1] => * ^
                 //    [2] => .(title)[class]{style}<>_
                 //    [3] => ....
                 //    [4] => .(title)[class]{style}<>_
                 if ($mModCol) {
                     $colModifier[$col] = new TexyModifier($mModCol);
                 }
                 if (isset($colModifier[$col])) {
                     $mod = clone $colModifier[$col];
                 } else {
                     $mod = new TexyModifier();
                 }
                 $mod->setProperties($mMod);
                 $elCell = new TexyTableCellElement();
                 $elCell->setName($isHead || $mHead === '*' ? 'th' : 'td');
                 $mod->decorate($tx, $elCell);
                 $elCell->text = $mContent;
                 $elRow->add($elCell);
                 $prevRow[$col] = $elCell;
                 $col++;
             }
             // even up with empty cells
             while ($col < $colCounter) {
                 if (isset($prevRow[$col]) && $lineMode) {
                     $prevRow[$col]->rowSpan++;
                     $prevRow[$col]->text .= "\n";
                 } else {
                     $elCell = new TexyTableCellElement();
                     $elCell->setName($isHead ? 'th' : 'td');
                     if (isset($colModifier[$col])) {
                         $colModifier[$col]->decorate($tx, $elCell);
                     }
                     $elRow->add($elCell);
                     $prevRow[$col] = $elCell;
                 }
                 $col++;
             }
             $colCounter = $col;
             if ($elRow->count()) {
                 $elPart->add($elRow);
                 $rowCounter++;
             } else {
                 // redundant row
                 foreach ($prevRow as $elCell) {
                     $elCell->rowSpan--;
                 }
             }
             continue;
         }
         break;
     }
     if ($elPart === NULL) {
         // invalid table
         return FALSE;
     }
     if ($elPart->getName() === 'thead') {
         // thead is optional, tbody is required
         $elPart->setName('tbody');
     }
     $this->finishPart($elPart);
     // event listener
     $tx->invokeHandlers('afterTable', array($parser, $el, $mod));
     return $el;
 }
示例#25
0
文件: Texy.php 项目: xxdavid/texy
 /**
  * Converts document in Texy! to (X)HTML code.
  *
  * @param  string   input text
  * @param  bool     is single line?
  * @return string   output HTML code
  */
 public function process($text, $singleLine = FALSE)
 {
     if ($this->processing) {
         throw new RuntimeException('Processing is in progress yet.');
     }
     // initialization
     $this->marks = array();
     $this->processing = TRUE;
     // speed-up
     if (is_array($this->allowedClasses)) {
         $this->_classes = array_flip($this->allowedClasses);
     } else {
         $this->_classes = $this->allowedClasses;
     }
     if (is_array($this->allowedStyles)) {
         $this->_styles = array_flip($this->allowedStyles);
     } else {
         $this->_styles = $this->allowedStyles;
     }
     // convert to UTF-8 (and check source encoding)
     $text = TexyUtf::toUtf($text, $this->encoding);
     if ($this->removeSoftHyphens) {
         $text = str_replace("­", '', $text);
     }
     // standardize line endings and spaces
     $text = self::normalize($text);
     // replace tabs with spaces
     $this->tabWidth = max(1, (int) $this->tabWidth);
     while (strpos($text, "\t") !== FALSE) {
         $text = TexyRegexp::replace($text, '#^([^\\t\\n]*+)\\t#mU', array($this, 'tabCb'));
     }
     // user before handler
     $this->invokeHandlers('beforeParse', array($this, &$text, $singleLine));
     // select patterns
     $this->_linePatterns = $this->linePatterns;
     $this->_blockPatterns = $this->blockPatterns;
     foreach ($this->_linePatterns as $name => $foo) {
         if (empty($this->allowed[$name])) {
             unset($this->_linePatterns[$name]);
         }
     }
     foreach ($this->_blockPatterns as $name => $foo) {
         if (empty($this->allowed[$name])) {
             unset($this->_blockPatterns[$name]);
         }
     }
     // parse Texy! document into internal DOM structure
     $this->DOM = TexyHtml::el();
     if ($singleLine) {
         $this->DOM->parseLine($this, $text);
     } else {
         $this->DOM->parseBlock($this, $text);
     }
     // user after handler
     $this->invokeHandlers('afterParse', array($this, $this->DOM, $singleLine));
     // converts internal DOM structure to final HTML code
     $html = $this->DOM->toHtml($this);
     // created by TexyParagraphModule and then protected
     $html = str_replace("\r", "\n", $html);
     $this->processing = FALSE;
     return TexyUtf::utf2html($html, $this->encoding);
 }
示例#26
0
 /**
  * Finish invocation.
  *
  * @param  TexyHandlerInvocation  handler invocation
  * @param  string   blocktype
  * @param  string   content
  * @param  string   additional parameter
  * @param  TexyModifier
  * @return TexyHtml|string|FALSE
  */
 public function solve($invocation, $blocktype, $s, $param, $mod)
 {
     $tx = $this->texy;
     $parser = $invocation->parser;
     if ($blocktype === 'block/texy') {
         $el = TexyHtml::el();
         $el->parseBlock($tx, $s, $parser->isIndented());
         return $el;
     }
     if (empty($tx->allowed[$blocktype])) {
         return FALSE;
     }
     if ($blocktype === 'block/texysource') {
         $s = Texy::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $el = TexyHtml::el();
         if ($param === 'line') {
             $el->parseLine($tx, $s);
         } else {
             $el->parseBlock($tx, $s);
         }
         $s = $el->toHtml($tx);
         $blocktype = 'block/code';
         $param = 'html';
         // to be continue (as block/code)
     }
     if ($blocktype === 'block/code') {
         $s = Texy::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $s = Texy::escapeHtml($s);
         $s = $tx->protect($s, Texy::CONTENT_BLOCK);
         $el = TexyHtml::el('pre');
         $mod->decorate($tx, $el);
         $el->attrs['class'][] = $param;
         // lang
         $el->create('code', $s);
         return $el;
     }
     if ($blocktype === 'block/default') {
         $s = Texy::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $el = TexyHtml::el('pre');
         $mod->decorate($tx, $el);
         $el->attrs['class'][] = $param;
         // lang
         $s = Texy::escapeHtml($s);
         $s = $tx->protect($s, Texy::CONTENT_BLOCK);
         $el->setText($s);
         return $el;
     }
     if ($blocktype === 'block/pre') {
         $s = Texy::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $el = TexyHtml::el('pre');
         $mod->decorate($tx, $el);
         $lineParser = new TexyLineParser($tx, $el);
         // special mode - parse only html tags
         $tmp = $lineParser->patterns;
         $lineParser->patterns = array();
         if (isset($tmp['html/tag'])) {
             $lineParser->patterns['html/tag'] = $tmp['html/tag'];
         }
         if (isset($tmp['html/comment'])) {
             $lineParser->patterns['html/comment'] = $tmp['html/comment'];
         }
         unset($tmp);
         $lineParser->parse($s);
         $s = $el->getText();
         $s = Texy::unescapeHtml($s);
         $s = Texy::escapeHtml($s);
         $s = $tx->unprotect($s);
         $s = $tx->protect($s, Texy::CONTENT_BLOCK);
         $el->setText($s);
         return $el;
     }
     if ($blocktype === 'block/html') {
         $s = trim($s, "\n");
         if ($s === '') {
             return "\n";
         }
         $el = TexyHtml::el();
         $lineParser = new TexyLineParser($tx, $el);
         // special mode - parse only html tags
         $tmp = $lineParser->patterns;
         $lineParser->patterns = array();
         if (isset($tmp['html/tag'])) {
             $lineParser->patterns['html/tag'] = $tmp['html/tag'];
         }
         if (isset($tmp['html/comment'])) {
             $lineParser->patterns['html/comment'] = $tmp['html/comment'];
         }
         unset($tmp);
         $lineParser->parse($s);
         $s = $el->getText();
         $s = Texy::unescapeHtml($s);
         $s = Texy::escapeHtml($s);
         $s = $tx->unprotect($s);
         return $tx->protect($s, Texy::CONTENT_BLOCK) . "\n";
     }
     if ($blocktype === 'block/text') {
         $s = trim($s, "\n");
         if ($s === '') {
             return "\n";
         }
         $s = Texy::escapeHtml($s);
         $s = str_replace("\n", TexyHtml::el('br')->startTag(), $s);
         // nl2br
         return $tx->protect($s, Texy::CONTENT_BLOCK) . "\n";
     }
     if ($blocktype === 'block/comment') {
         return "\n";
     }
     if ($blocktype === 'block/div') {
         $s = Texy::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $el = TexyHtml::el('div');
         $mod->decorate($tx, $el);
         $el->parseBlock($tx, $s, $parser->isIndented());
         // TODO: INDENT or NORMAL ?
         return $el;
     }
     if ($blocktype === 'block/section') {
         $s = Texy::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $el = TexyHtml::el('section');
         $mod->decorate($tx, $el);
         $el->parseBlock($tx, $s, $parser->isIndented());
         // TODO: INDENT or NORMAL ?
         return $el;
     }
     if ($blocktype === 'block/article') {
         $s = Texy::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $el = TexyHtml::el('article');
         $mod->decorate($tx, $el);
         $el->parseBlock($tx, $s, $parser->isIndented());
         // TODO: INDENT or NORMAL ?
         return $el;
     }
     if ($blocktype === 'block/aside') {
         $s = Texy::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $el = TexyHtml::el('aside');
         $mod->decorate($tx, $el);
         $el->parseBlock($tx, $s, $parser->isIndented());
         // TODO: INDENT or NORMAL ?
         return $el;
     }
     if ($blocktype === 'block/header') {
         $s = Texy::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $el = TexyHtml::el('header');
         $mod->decorate($tx, $el);
         $el->parseBlock($tx, $s, $parser->isIndented());
         // TODO: INDENT or NORMAL ?
         return $el;
     }
     if ($blocktype === 'block/footer') {
         $s = Texy::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $el = TexyHtml::el('footer');
         $mod->decorate($tx, $el);
         $el->parseBlock($tx, $s, $parser->isIndented());
         // TODO: INDENT or NORMAL ?
         return $el;
     }
     if ($blocktype === 'block/nav') {
         $s = Texy::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $el = TexyHtml::el('nav');
         $mod->decorate($tx, $el);
         $el->parseBlock($tx, $s, $parser->isIndented());
         // TODO: INDENT or NORMAL ?
         return $el;
     }
     return FALSE;
 }
示例#27
0
 /**
  * Converts document in Texy! to (X)HTML code.
  *
  * @param  string   input text
  * @param  bool     is single line?
  * @return string   output HTML code
  */
 public function process($text, $singleLine = FALSE)
 {
     if ($this->processing) {
         throw new InvalidStateException('Processing is in progress yet.');
     }
     // initialization
     $this->marks = array();
     $this->processing = TRUE;
     // speed-up
     if (is_array($this->allowedClasses)) {
         $this->_classes = array_flip($this->allowedClasses);
     } else {
         $this->_classes = $this->allowedClasses;
     }
     if (is_array($this->allowedStyles)) {
         $this->_styles = array_flip($this->allowedStyles);
     } else {
         $this->_styles = $this->allowedStyles;
     }
     // convert to UTF-8 (and check source encoding)
     $text = TexyUtf::toUtf($text, $this->encoding);
     if ($this->removeSoftHyphens) {
         $text = str_replace("­", '', $text);
     }
     // standardize line endings and spaces
     $text = self::normalize($text);
     // replace tabs with spaces
     $this->tabWidth = max(1, (int) $this->tabWidth);
     while (strpos($text, "\t") !== FALSE) {
         $text = preg_replace_callback('#^(.*)\\t#mU', array($this, 'tabCb'), $text);
     }
     // user before handler
     $this->invokeHandlers('beforeParse', array($this, &$text, $singleLine));
     // select patterns
     $this->_linePatterns = $this->linePatterns;
     $this->_blockPatterns = $this->blockPatterns;
     foreach ($this->_linePatterns as $name => $foo) {
         if (empty($this->allowed[$name])) {
             unset($this->_linePatterns[$name]);
         }
     }
     foreach ($this->_blockPatterns as $name => $foo) {
         if (empty($this->allowed[$name])) {
             unset($this->_blockPatterns[$name]);
         }
     }
     // parse Texy! document into internal DOM structure
     $this->DOM = TexyHtml::el();
     if ($singleLine) {
         $this->DOM->parseLine($this, $text);
     } else {
         $this->DOM->parseBlock($this, $text);
     }
     // user after handler
     $this->invokeHandlers('afterParse', array($this, $this->DOM, $singleLine));
     // converts internal DOM structure to final HTML code
     $html = $this->DOM->toHtml($this);
     // this notice should remain
     if (self::$advertisingNotice) {
         $html .= "\n<!-- by Texy2! -->";
         if (self::$advertisingNotice === 'once') {
             self::$advertisingNotice = FALSE;
         }
     }
     $this->processing = FALSE;
     return TexyUtf::utf2html($html, $this->encoding);
 }
示例#28
0
 public function blockHandler($invocation, $blocktype, $content, $lang, $modifier)
 {
     if ($blocktype !== 'block/code') {
         return $invocation->proceed();
         //vstup se nebude zpracovavat
     }
     $highlighter = new \FSHL\Highlighter(new \FSHL\Output\HtmlManual(), \FSHL\Highlighter::OPTION_TAB_INDENT);
     $texy = $invocation->getTexy();
     $content = \Texy::outdent($content);
     //Set correct lexer:
     switch (strtoupper($lang)) {
         case 'C':
         case 'CPP':
             $lexer = new \FSHL\Lexer\Cpp();
             break;
         case 'CSS':
             $lexer = new \FSHL\Lexer\Css();
             break;
         case 'HTML':
             $lexer = new \FSHL\Lexer\Html();
             break;
             //HtmlOnly lexer
         //HtmlOnly lexer
         case 'JAVA':
             $lexer = new \FSHL\Lexer\Java();
             break;
         case 'JS':
         case 'JAVASCRIPT':
             $lexer = new \FSHL\Lexer\Javascript();
             break;
         case 'NEON':
             $lexer = new \FSHL\Lexer\Neon();
             break;
         case 'PHP':
             $lexer = new \FSHL\Lexer\Php();
             break;
         case 'PYTHON':
             $lexer = new \FSHL\Lexer\Python();
             break;
         case 'SQL':
             $lexer = new \FSHL\Lexer\Sql();
             break;
         case 'TEX':
             $lexer = new \FSHL\Lexer\Tex();
             break;
         case 'TEXY':
             $lexer = new \FSHL\Lexer\Texy();
             break;
         default:
             $lexer = new \FSHL\Lexer\Minimal();
     }
     $content = $highlighter->highlight($content, $lexer);
     $content = $texy->protect($content, \Texy::CONTENT_BLOCK);
     $elPre = \TexyHtml::el('pre');
     if ($modifier) {
         $modifier->decorate($texy, $elPre);
     }
     $elPre->attrs['class'] = strtolower($lang);
     $elPre->create('code', $content);
     return $elPre;
 }
示例#29
0
 public function process($text, $singleLine = FALSE)
 {
     if ($this->processing) {
         throw new InvalidStateException('Processing is in progress yet.');
     }
     $this->marks = array();
     $this->processing = TRUE;
     if (is_array($this->allowedClasses)) {
         $this->_classes = array_flip($this->allowedClasses);
     } else {
         $this->_classes = $this->allowedClasses;
     }
     if (is_array($this->allowedStyles)) {
         $this->_styles = array_flip($this->allowedStyles);
     } else {
         $this->_styles = $this->allowedStyles;
     }
     $text = TexyUtf::toUtf($text, $this->encoding);
     if ($this->removeSoftHyphens) {
         $text = str_replace("Β­", '', $text);
     }
     $text = self::normalize($text);
     $this->tabWidth = max(1, (int) $this->tabWidth);
     while (strpos($text, "\t") !== FALSE) {
         $text = preg_replace_callback('#^(.*)\\t#mU', array($this, 'tabCb'), $text);
     }
     $this->invokeHandlers('beforeParse', array($this, &$text, $singleLine));
     $this->_linePatterns = $this->linePatterns;
     $this->_blockPatterns = $this->blockPatterns;
     foreach ($this->_linePatterns as $name => $foo) {
         if (empty($this->allowed[$name])) {
             unset($this->_linePatterns[$name]);
         }
     }
     foreach ($this->_blockPatterns as $name => $foo) {
         if (empty($this->allowed[$name])) {
             unset($this->_blockPatterns[$name]);
         }
     }
     $this->DOM = TexyHtml::el();
     if ($singleLine) {
         $this->DOM->parseLine($this, $text);
     } else {
         $this->DOM->parseBlock($this, $text);
     }
     $this->invokeHandlers('afterParse', array($this, $this->DOM, $singleLine));
     $html = $this->DOM->toHtml($this);
     if (self::$advertisingNotice) {
         $html .= "\n<!-- by Texy2! -->";
         if (self::$advertisingNotice === 'once') {
             self::$advertisingNotice = FALSE;
         }
     }
     $this->processing = FALSE;
     return TexyUtf::utf2html($html, $this->encoding);
 }
示例#30
0
 /**
  * Finish invocation.
  *
  * @param  TexyHandlerInvocation  handler invocation
  * @param  TexyImage
  * @param  TexyLink
  * @return TexyHtml|FALSE
  */
 public function solve($invocation, TexyImage $image, $link)
 {
     if ($image->URL == NULL) {
         return FALSE;
     }
     $tx = $this->texy;
     $mod = $image->modifier;
     $alt = $mod->title;
     $mod->title = NULL;
     $hAlign = $mod->hAlign;
     $mod->hAlign = NULL;
     $el = TexyHtml::el('img');
     $el->attrs['src'] = NULL;
     // trick - move to front
     $mod->decorate($tx, $el);
     $el->attrs['src'] = Texy::prependRoot($image->URL, $this->root);
     if (!isset($el->attrs['alt'])) {
         if ($alt !== NULL) {
             $el->attrs['alt'] = $tx->typographyModule->postLine($alt);
         } else {
             $el->attrs['alt'] = $this->defaultAlt;
         }
     }
     if ($hAlign) {
         $var = $hAlign . 'Class';
         // leftClass, rightClass
         if (!empty($this->{$var})) {
             $el->attrs['class'][] = $this->{$var};
         } elseif (empty($tx->alignClasses[$hAlign])) {
             $el->attrs['style']['float'] = $hAlign;
         } else {
             $el->attrs['class'][] = $tx->alignClasses[$hAlign];
         }
     }
     if (!is_int($image->width) || !is_int($image->height) || $image->asMax) {
         // autodetect fileRoot
         if ($this->fileRoot === NULL && isset($_SERVER['SCRIPT_FILENAME'])) {
             $this->fileRoot = dirname($_SERVER['SCRIPT_FILENAME']) . '/' . $this->root;
         }
         // detect dimensions
         // absolute URL & security check for double dot
         if (Texy::isRelative($image->URL) && strpos($image->URL, '..') === FALSE) {
             $file = rtrim($this->fileRoot, '/\\') . '/' . $image->URL;
             if (@is_file($file)) {
                 $size = getImageSize($file);
                 if (is_array($size)) {
                     if ($image->asMax) {
                         $ratio = 1;
                         if (is_int($image->width)) {
                             $ratio = min($ratio, $image->width / $size[0]);
                         }
                         if (is_int($image->height)) {
                             $ratio = min($ratio, $image->height / $size[1]);
                         }
                         $image->width = round($ratio * $size[0]);
                         $image->height = round($ratio * $size[1]);
                     } elseif (is_int($image->width)) {
                         $ratio = round($size[1] / $size[0] * $image->width);
                         $image->height = round($size[1] / $size[0] * $image->width);
                     } elseif (is_int($image->height)) {
                         $image->width = round($size[0] / $size[1] * $image->height);
                     } else {
                         $image->width = $size[0];
                         $image->height = $size[1];
                     }
                 }
             }
         }
     }
     $el->attrs['width'] = $image->width;
     $el->attrs['height'] = $image->height;
     // onmouseover actions generate
     if ($image->overURL !== NULL) {
         $overSrc = Texy::prependRoot($image->overURL, $this->root);
         $el->attrs['onmouseover'] = 'this.src=\'' . addSlashes($overSrc) . '\'';
         $el->attrs['onmouseout'] = 'this.src=\'' . addSlashes($el->attrs['src']) . '\'';
         $el->attrs['onload'] = str_replace('%i', addSlashes($overSrc), $this->onLoad);
         $tx->summary['preload'][] = $overSrc;
     }
     $tx->summary['images'][] = $el->attrs['src'];
     if ($link) {
         return $tx->linkModule->solve(NULL, $link, $el);
     }
     return $el;
 }