public function getHighlightFuture($language, $source) { if ($language === null) { $language = PhutilLanguageGuesser::guessLanguage($source); } $have_pygments = !empty($this->config['pygments.enabled']); if ($language == 'php' && xhpast_is_available()) { return id(new PhutilXHPASTSyntaxHighlighter())->getHighlightFuture($source); } if ($language == 'console') { return id(new PhutilConsoleSyntaxHighlighter())->getHighlightFuture($source); } if ($language == 'diviner' || $language == 'remarkup') { return id(new PhutilDivinerSyntaxHighlighter())->getHighlightFuture($source); } if ($language == 'rainbow') { return id(new PhutilRainbowSyntaxHighlighter())->getHighlightFuture($source); } if ($language == 'php') { return id(new PhutilLexerSyntaxHighlighter())->setConfig('lexer', new PhutilPHPFragmentLexer())->setConfig('language', 'php')->getHighlightFuture($source); } if ($language == 'py') { return id(new PhutilLexerSyntaxHighlighter())->setConfig('lexer', new PhutilPythonFragmentLexer())->setConfig('language', 'py')->getHighlightFuture($source); } if ($language == 'invisible') { return id(new PhutilInvisibleSyntaxHighlighter())->getHighlightFuture($source); } if ($have_pygments) { return id(new PhutilPygmentsSyntaxHighlighter())->setConfig('language', $language)->getHighlightFuture($source); } return id(new PhutilDefaultSyntaxHighlighter())->getHighlightFuture($source); }
public function testGuessing() { $dir = dirname(__FILE__) . '/languageguesser/'; foreach (Filesystem::listDirectory($dir, $hidden = false) as $test) { $source = Filesystem::readFile($dir . $test); if (strpos($test, '.') !== false) { $expect = head(explode('.', $test)); } else { $expect = null; } $this->assertEqual($expect, PhutilLanguageGuesser::guessLanguage($source), "Guessed language for '{$test}'."); } }
public function getHighlightFuture($language, $source) { if ($language === null) { $language = PhutilLanguageGuesser::guessLanguage($source); } $have_pygments = !empty($this->config['pygments.enabled']); if ($language == 'php' && PhutilXHPASTBinary::isAvailable()) { return id(new PhutilXHPASTSyntaxHighlighter())->getHighlightFuture($source); } if ($language == 'console') { return id(new PhutilConsoleSyntaxHighlighter())->getHighlightFuture($source); } if ($language == 'diviner' || $language == 'remarkup') { return id(new PhutilDivinerSyntaxHighlighter())->getHighlightFuture($source); } if ($language == 'rainbow') { return id(new PhutilRainbowSyntaxHighlighter())->getHighlightFuture($source); } if ($language == 'php') { return id(new PhutilLexerSyntaxHighlighter())->setConfig('lexer', new PhutilPHPFragmentLexer())->setConfig('language', 'php')->getHighlightFuture($source); } if ($language == 'py') { return id(new PhutilLexerSyntaxHighlighter())->setConfig('lexer', new PhutilPythonFragmentLexer())->setConfig('language', 'py')->getHighlightFuture($source); } if ($language == 'json') { return id(new PhutilLexerSyntaxHighlighter())->setConfig('lexer', new PhutilJSONFragmentLexer())->getHighlightFuture($source); } if ($language == 'invisible') { return id(new PhutilInvisibleSyntaxHighlighter())->getHighlightFuture($source); } // Don't invoke Pygments for plain text, since it's expensive and has // no effect. if ($language !== 'text' && $language !== 'txt') { if ($have_pygments) { return id(new PhutilPygmentsSyntaxHighlighter())->setConfig('language', $language)->getHighlightFuture($source); } } return id(new PhutilDefaultSyntaxHighlighter())->getHighlightFuture($source); }
public function markupText($text, $children) { if (preg_match('/^\\s*```/', $text)) { // If this is a ```-style block, trim off the backticks and any leading // blank line. $text = preg_replace('/^\\s*```(\\s*\\n)?/', '', $text); $text = preg_replace('/```\\s*$/', '', $text); } $lines = explode("\n", $text); while ($lines && !strlen(last($lines))) { unset($lines[last_key($lines)]); } $options = array('counterexample' => false, 'lang' => null, 'name' => null, 'lines' => null); $parser = new PhutilSimpleOptions(); $custom = $parser->parse(head($lines)); if ($custom) { $valid = true; foreach ($custom as $key => $value) { if (!array_key_exists($key, $options)) { $valid = false; break; } } if ($valid) { array_shift($lines); $options = $custom + $options; } } // Normalize the text back to a 0-level indent. $min_indent = 80; foreach ($lines as $line) { for ($ii = 0; $ii < strlen($line); $ii++) { if ($line[$ii] != ' ') { $min_indent = min($ii, $min_indent); break; } } } $text = implode("\n", $lines); if ($min_indent) { $indent_string = str_repeat(' ', $min_indent); $text = preg_replace('/^' . $indent_string . '/m', '', $text); } if ($this->getEngine()->isTextMode()) { $out = array(); $header = array(); if ($options['counterexample']) { $header[] = 'counterexample'; } if ($options['name'] != '') { $header[] = 'name=' . $options['name']; } if ($header) { $out[] = implode(', ', $header); } $text = preg_replace('/^/m', ' ', $text); $out[] = $text; return implode("\n", $out); } if (empty($options['lang'])) { // If the user hasn't specified "lang=..." explicitly, try to guess the // language. If we fail, fall back to configured defaults. $lang = PhutilLanguageGuesser::guessLanguage($text); if (!$lang) { $lang = nonempty($this->getEngine()->getConfig('phutil.codeblock.language-default'), 'text'); } $options['lang'] = $lang; } $code_body = $this->highlightSource($text, $options); $name_header = null; if ($this->getEngine()->isHTMLMailMode()) { $header_attributes = array('style' => 'padding: 6px 8px; background: #fdf5d4; color: rgba(0,0,0,.75); font-weight: bold; display: inline-block; border-top: 1px solid #f1c40f; border-left: 1px solid #f1c40f; border-right: 1px solid #f1c40f; margin-bottom: -1px;'); } else { $header_attributes = array('class' => 'remarkup-code-header'); } if ($options['name']) { $name_header = phutil_tag('div', $header_attributes, $options['name']); } $class = 'remarkup-code-block'; if ($options['counterexample']) { $class = 'remarkup-code-block code-block-counterexample'; } $attributes = array('class' => $class, 'data-code-lang' => $options['lang'], 'data-sigil' => 'remarkup-code-block'); return phutil_tag('div', $attributes, array($name_header, $code_body)); }
public function markupText($text) { if (preg_match('/^```/', $text)) { // If this is a ```-style block, trim off the backticks. $text = preg_replace('/```\\s*$/', '', substr($text, 3)); } $lines = explode("\n", $text); $options = array('counterexample' => false, 'lang' => null, 'name' => null, 'lines' => null); $custom = PhutilSimpleOptions::parse(head($lines)); if ($custom) { $valid = true; foreach ($custom as $key => $value) { if (!array_key_exists($key, $options)) { $valid = false; break; } } if ($valid) { array_shift($lines); $options = $custom + $options; } } if ($options['counterexample']) { $aux_class = ' remarkup-counterexample'; } else { $aux_class = null; } // Normalize the text back to a 0-level indent. $min_indent = 80; foreach ($lines as $line) { for ($ii = 0; $ii < strlen($line); $ii++) { if ($line[$ii] != ' ') { $min_indent = min($ii, $min_indent); break; } } } if ($min_indent) { $indent_string = str_repeat(' ', $min_indent); $text = preg_replace('/^' . $indent_string . '/m', '', implode("\n", $lines)); } else { $text = implode("\n", $lines); } if (empty($options['lang'])) { // If the user hasn't specified "lang=..." explicitly, try to guess the // language. If we fail, fall back to configured defaults. $lang = PhutilLanguageGuesser::guessLanguage($text); if (!$lang) { $lang = nonempty($this->getEngine()->getConfig('phutil.codeblock.language-default'), 'php'); } $options['lang'] = $lang; } $name_header = null; if ($options['name']) { $name_header = phutil_render_tag('div', array('class' => 'remarkup-code-header'), phutil_escape_html($options['name'])); } $aux_style = null; if ($options['lines']) { // Put a minimum size on this because the scrollbar is otherwise // unusable. $height = max(6, (int) $options['lines']); $aux_style = 'max-height: ' . 2 * $height . 'em;'; } $engine = $this->getEngine()->getConfig('syntax-highlighter.engine'); if (!$engine) { $engine = 'PhutilDefaultSyntaxHighlighterEngine'; } $engine = newv($engine, array()); $engine->setConfig('pygments.enabled', $this->getEngine()->getConfig('pygments.enabled')); $code_body = phutil_render_tag('pre', array('class' => 'remarkup-code' . $aux_class, 'style' => $aux_style), $engine->highlightSource($options['lang'], $text)); return phutil_render_tag('div', array('class' => 'remarkup-code-block', 'data-code-lang' => $options['lang']), $name_header . $code_body); }
public function markupText($text) { if (preg_match('/^```/', $text)) { // If this is a ```-style block, trim off the backticks. $text = preg_replace('/```\\s*$/', '', substr($text, 3)); } $lines = explode("\n", $text); $options = array('counterexample' => false, 'lang' => null, 'name' => null, 'lines' => null); $parser = new PhutilSimpleOptions(); $custom = $parser->parse(head($lines)); if ($custom) { $valid = true; foreach ($custom as $key => $value) { if (!array_key_exists($key, $options)) { $valid = false; break; } } if ($valid) { array_shift($lines); $options = $custom + $options; } } // Normalize the text back to a 0-level indent. $min_indent = 80; foreach ($lines as $line) { for ($ii = 0; $ii < strlen($line); $ii++) { if ($line[$ii] != ' ') { $min_indent = min($ii, $min_indent); break; } } } $text = implode("\n", $lines); if ($min_indent) { $indent_string = str_repeat(' ', $min_indent); $text = preg_replace('/^' . $indent_string . '/m', '', $text); } if ($this->getEngine()->isTextMode()) { $out = array(); $header = array(); if ($options['counterexample']) { $header[] = 'counterexample'; } if ($options['name'] != '') { $header[] = 'name=' . $options['name']; } if ($header) { $out[] = implode(', ', $header); } $text = preg_replace('/^/m', ' ', $text); $text = preg_replace('/^\\s+$/m', '', $text); $out[] = $text; return implode("\n", $out); } if (empty($options['lang'])) { // If the user hasn't specified "lang=..." explicitly, try to guess the // language. If we fail, fall back to configured defaults. $lang = PhutilLanguageGuesser::guessLanguage($text); if (!$lang) { $lang = nonempty($this->getEngine()->getConfig('phutil.codeblock.language-default'), 'php'); } $options['lang'] = $lang; } $code_body = $this->highlightSource($text, $options); $name_header = null; if ($options['name']) { $name_header = phutil_tag('div', array('class' => 'remarkup-code-header'), $options['name']); } return phutil_tag('div', array('class' => 'remarkup-code-block', 'data-code-lang' => $options['lang']), array($name_header, $code_body)); }