/** * @return Texy */ public static function createTexy() { $texy = new Texy(); $texy->encoding = 'utf-8'; $texy->setOutputMode(\Texy::HTML5); // from https://github.com/nette/web-content/blob/convertor/src/Wiki/Convertor.php $texy->linkModule->root = ''; $texy->alignClasses['left'] = 'left'; $texy->alignClasses['right'] = 'right'; $texy->emoticonModule->class = 'smiley'; $texy->headingModule->top = 1; $texy->headingModule->generateID = TRUE; $texy->tabWidth = 4; $texy->typographyModule->locale = 'cs'; //en ? $texy->tableModule->evenClass = 'alt'; $texy->dtd['body'][1]['style'] = TRUE; $texy->allowed['longwords'] = FALSE; $texy->allowed['block/html'] = FALSE; $texy->phraseModule->tags['phrase/strong'] = 'b'; $texy->phraseModule->tags['phrase/em'] = 'i'; $texy->phraseModule->tags['phrase/em-alt'] = 'i'; $texy->phraseModule->tags['phrase/acronym'] = 'abbr'; $texy->phraseModule->tags['phrase/acronym-alt'] = 'abbr'; $texy->addHandler('block', array('TexyFactory', 'blockHandler')); return $texy; }
/** * @return \Texy */ public function createTexyForPage() { $texy = new \Texy(); $texy->headingModule->top = 3; $texy->setOutputMode(\Texy::HTML5); // Images $texy->imageModule->root = $this->request->getUrl()->getBaseUrl() . $this->imagesRoot; $texy->imageModule->fileRoot = $this->imagesFileRoot; $texy->addHandler('block', [$this, 'blockHandler']); return $texy; }
*/ function imageHandler($invocation, $image, $link) { $parts = explode(':', $image->URL); if (count($parts) !== 2) { return $invocation->proceed(); } switch ($parts[0]) { case 'youtube': $video = htmlSpecialChars($parts[1]); $dimensions = 'width="' . ($image->width ? $image->width : 425) . '" height="' . ($image->height ? $image->height : 350) . '"'; $code = '<div><object ' . $dimensions . '>' . '<param name="movie" value="http://www.youtube.com/v/' . $video . '" /><param name="wmode" value="transparent" />' . '<embed src="http://www.youtube.com/v/' . $video . '" type="application/x-shockwave-flash" wmode="transparent" ' . $dimensions . ' /></object></div>'; $texy = $invocation->getTexy(); return $texy->protect($code, Texy::CONTENT_BLOCK); } return $invocation->proceed(); } $texy = new Texy(); $texy->addHandler('image', 'imageHandler'); // processing $text = file_get_contents('sample.texy'); $html = $texy->process($text); // that's all folks! // echo formated output header('Content-type: text/html; charset=utf-8'); echo $html; // echo generated HTML code echo '<hr />'; echo '<pre>'; echo htmlSpecialChars($html); echo '</pre>';
} $name = $names[$refName]; $el = new Texy\HtmlElement('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; } $texy = new Texy(); // references link [1] [2] will be processed through user function $texy->addHandler('newReference', 'newReferenceHandler'); // configuration Texy\Configurator::safeMode($texy); // safe mode prevets attacker to inject some HTML code and disable images // how generally disable links or enable images? here is a way: // $disallow = array('image', 'figure', 'linkReference', 'linkEmail', 'linkURL', 'linkQuick'); // foreach ($diallow as $item) // $texy->allowed[$item] = FALSE; // processing $text = file_get_contents('sample.texy'); $html = $texy->process($text); // that's all folks! // echo formated output header('Content-type: text/html; charset=utf-8'); echo $html; // do some antispam filtering - this is just very simple example ;-)
<?php /** * TEXY! USER HANDLER DEMO */ // include Texy! require_once dirname(__FILE__) . '/../../src/texy.php'; $texy = new Texy(); $texy->addHandler('emoticon', array('myHandler', 'emoticon')); $texy->addHandler('image', array('myHandler', 'image')); $texy->addHandler('linkReference', array('myHandler', 'linkReference')); $texy->addHandler('linkEmail', array('myHandler', 'linkEmail')); $texy->addHandler('linkURL', array('myHandler', 'linkURL')); $texy->addHandler('phrase', array('myHandler', 'phrase')); $texy->addHandler('newReference', array('myHandler', 'newReference')); $texy->addHandler('htmlComment', array('myHandler', 'htmlComment')); $texy->addHandler('htmlTag', array('myHandler', 'htmlTag')); $texy->addHandler('script', array('myHandler', 'script')); //$texy->addHandler('paragraph', array('myHandler', 'paragraph')); $texy->addHandler('figure', array('myHandler', 'figure')); $texy->addHandler('heading', array('myHandler', 'heading')); $texy->addHandler('horizline', array('myHandler', 'horizline')); $texy->addHandler('block', array('myHandler', 'block')); $texy->addHandler('afterList', array('myHandler', 'afterList')); $texy->addHandler('afterDefinitionList', array('myHandler', 'afterDefinitionList')); $texy->addHandler('afterTable', array('myHandler', 'afterTable')); $texy->addHandler('afterBlockquote', array('myHandler', 'afterBlockquote')); $texy->addHandler('beforeParse', array('myHandler', 'beforeParse')); $texy->addHandler('afterParse', array('myHandler', 'afterParse')); class myHandler {
$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; } $texy = new Texy(); $texy->addHandler('block', 'blockHandler'); // prepare CSS stylesheet $texy->styleSheet = 'pre { padding:10px } '; // processing $text = file_get_contents('sample.texy'); $html = $texy->process($text); // that's all folks! // echo Geshi Stylesheet header('Content-type: text/html; charset=utf-8'); echo '<style type="text/css">' . $texy->styleSheet . '</style>'; echo '<title>' . $texy->headingModule->title . '</title>'; // echo formated output echo $html; // and echo generated HTML code echo '<hr />'; echo '<pre>';
// is there link? if (!$link) { return $invocation->proceed(); } if (Texy::isRelative($link->URL)) { // modifiy link $link->URL = 'index?page=' . urlencode($link->URL); } elseif (substr($link->URL, 0, 5) === 'wiki:') { // modifiy link $link->URL = 'http://en.wikipedia.org/wiki/Special:Search?search=' . urlencode(substr($link->URL, 5)); } return $invocation->proceed(); } $texy = new Texy(); // configuration $texy->addHandler('phrase', 'phraseHandler'); // processing $text = file_get_contents('sample.texy'); $html = $texy->process($text); // that's all folks! // echo formated output header('Content-type: text/html; charset=utf-8'); echo $html; // echo all embedded links echo '<hr />'; echo '<pre>'; print_r($texy->summary['links']); echo '</pre>'; // and echo generated HTML code echo '<hr />'; echo '<pre>';
static function formattingByTexy($source) { static $texy; if (is_null($texy)) { if (!class_exists('Texy', false)) { $dir = Q::ini('vendor_dir'); require_once "{$dir}/geshi/geshi.php"; require_once "{$dir}/texy/texy.php"; } Texy::$advertisingNotice = false; $texy = new Texy(); $options = self::$_texy_options; foreach ($options as $module => $config) { foreach ($config as $key => $value) { $m = $module . 'Module'; $texy->{$m}->{$key} = $value; } } $texy->addHandler('block', array(__CLASS__, 'texyBlockHandler')); } return $texy->process($source); }
/** * 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')); }
// 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; } $texy = new Texy(); $texy->addHandler('figure', 'figureHandler'); // optionally set CSS classes /* $texy->figureModule->class = 'figure'; $texy->figureModule->leftClass = 'figure-left'; $texy->figureModule->rightClass = 'figure-right'; */ // processing $text = file_get_contents('sample.texy'); $html = $texy->process($text); // that's all folks! // echo formated output header('Content-type: text/html; charset=utf-8'); echo $html; // echo generated HTML code echo '<hr />';
function texyla($content, $texyCfg, $charset = 'utf-8', $oneLine = false) { if (empty($content)) { # protože je obsah prázdný vrátíme ho prázdný zpátky bez zpracování return $content; } if (!function_exists('iconv') && $charset != 'utf-8') { # ověření existence fce iconv(), která se používá pro zmenu # kodování vstupního textu při jiném než utf-8 kodování trigger_error(texylaErrorMsg(TEXYLA_ICONV_MISSING), E_USER_ERROR); } # jaky pouzit configurační soubor pro zpracování vstupního textu # defaultní hodnota je forum, takže není třeba uvádět. $texyCfg = texylaTexyCfg($texyCfg); # sestaveni cesty ke konfigu $texyCfgFile = dirname(__FILE__) . '/cfg/' . $texyCfg . '.php'; if (!is_bool($oneLine)) { # pokud není bool nastavíme na false (blokový text) $oneLine = false; } if (!class_exists('Texy')) { # Neexistuje třída Texy trigger_error(texylaErrorMsg(TEXYLA_CLASS_NOT_TEXY_FOUND, $texyFile), E_USER_ERROR); } # iniciace texy $texy = new Texy(); $texy->alignClasses['left'] = 'fl'; $texy->alignClasses['right'] = 'fr'; # nastavíme kódování v kterém je zpracováváný text # default je utf-8, není třeba uvádět při volání funkce texyla() [pokud nenásleduje další parametr] $texy->encoding = $charset; # proměnná, podle které se řídí přidávání hlášky <!-- by Texy2! --> na konec zpracovávaného textu # $GLOBALS['Texy::$advertisingNotice'] = false; # verze pro php5 Texy::$advertisingNotice = false; # Odstranění diakritiky z textu, vytvoření if ($texyCfg == 'webalize') { /* ******************************************************************************************* !!! Toto je v Testovací fázi !!! Bugreporty prosím na http://texyla.jaknato.com/khostu.php ******************************************************************************************* Jedná se o odstranění diakritiky... Výsledek obsahuje pouze a-z, čísla a spojovník. Není třeba načítat konfiguraci, Pokud používáte jiné kódování než je utf-8, je text překodován na utf-8 a je z něj odstraněna diakritika, výsledný text je čisté ASCII, takže se zpštně nepřevádí na původní kódóvání. Poznámky dgx k webalize: ======================== Je však možné povolit i další ASCII znaky: $nadpis = "článek/PHP 5.2.1 a funkce is_array()"; echo Texy::webalize($nadpis); // standardní chování → clanek-php-5-2-1-a-funkce-is-array $addChar = '/_.';// navíc povolíme znaky: / _ . echo Texy::webalize($nadpis,$addChar); → clanek/php-5.2.1-a-funkce-is_array Ještě dodám, že funkce funguje korektně i při chybné implementaci iconv (glibc). */ $content = strtolower($charset) == 'utf-8' ? $content : iconv($charset, 'utf-8', $content); $addChar = ''; return Texy::webalize($content, $addChar); } # kontrola existence konfiguračního souboru if (!file_exists($texyCfgFile)) { # neexistuje (nebyl nalezen/includován) soubor s konfigurací pro texy return texylaErrorMsg(TEXYLA_FILE_CFG_NOT_FOUND, $texyCfgFile); } # includujeme soubor s nastavením pro Texy! if (!(include $texyCfgFile)) { # Nepodařilo se načíst konfigurační soubor, # nejspíš špatné práva pro přístup k souboru return texylaErrorMsg(TEXYLA_ACCESS_DENIED, $texyFile); } # kontrola existence pomocné třídy FshlHandler (propojení Texy s fshlParser) # a třídy fshlParser (ta se stará o samotné obarvení kodu) if (function_exists('TexylaFSHLBlockHandler') && class_exists('fshlParser') && !empty($useFSHL) && $useFSHL === true) { # iniciace pomocné třídy starající se o obarvení zdrojovách kódů # Autor třídy je: Juraj 'hvge' Durech $texy->addHandler('block', 'TexylaFSHLBlockHandler'); } # Provedeme zpracování poslaného obsahu pomocí Texy! if (!empty($addTargetBlank) && $addTargetBlank === true) { return preg_replace_callback("~<a href~iU", "texylaAddTargetBlank", $texy->process($content, $oneLine)); } return $texy->process($content, $oneLine); }
/** * Texy factory * * @return \Texy */ protected function createTexy() { $texy = new \Texy(); $texy->encoding = 'utf-8'; $texy->setOutputMode(\Texy::HTML5); $texy->headingModule->top = 3; $texy->addHandler('image', ['Zax\\Texy\\Youtube', 'imageHandler']); return $texy; }