Page MenuHomePhabricator

D14292.id34498.diff
No OneTemporary

D14292.id34498.diff

diff --git a/.arclint b/.arclint
--- a/.arclint
+++ b/.arclint
@@ -1,6 +1,7 @@
{
"exclude": [
- "(^externals/)"
+ "(^externals/)",
+ "(/__tests__/data/)"
],
"linters": {
"chmod": {
diff --git a/scripts/test/highlight.php b/scripts/test/highlight.php
new file mode 100755
--- /dev/null
+++ b/scripts/test/highlight.php
@@ -0,0 +1,28 @@
+#!/usr/bin/env php
+<?php
+
+require_once dirname(__FILE__).'/../__init_script__.php';
+
+$args = new PhutilArgumentParser($argv);
+$args->setTagline(pht('test syntax highlighters'));
+$args->setSynopsis(<<<EOHELP
+**highlight.php** [__options__]
+ Syntax highlight a corpus read from stdin.
+EOHELP
+ );
+$args->parseStandardArguments();
+$args->parse(
+ array(
+ array(
+ 'name' => 'language',
+ 'param' => 'language',
+ 'help' => pht('Choose the highlight language.'),
+ ),
+ ));
+
+$language = $args->getArg('language');
+$corpus = file_get_contents('php://stdin');
+
+echo id(new PhutilDefaultSyntaxHighlighterEngine())
+ ->setConfig('pygments.enabled', true)
+ ->highlightSource($language, $corpus);
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -205,6 +205,8 @@
'PhutilIrreducibleRuleParserGeneratorException' => 'parser/generator/exception/PhutilIrreducibleRuleParserGeneratorException.php',
'PhutilJIRAAuthAdapter' => 'auth/PhutilJIRAAuthAdapter.php',
'PhutilJSON' => 'parser/PhutilJSON.php',
+ 'PhutilJSONFragmentLexer' => 'lexer/PhutilJSONFragmentLexer.php',
+ 'PhutilJSONFragmentLexerHighlighterTestCase' => 'markup/syntax/highlighter/__tests__/PhutilJSONFragmentLexerHighlighterTestCase.php',
'PhutilJSONParser' => 'parser/PhutilJSONParser.php',
'PhutilJSONParserException' => 'parser/exception/PhutilJSONParserException.php',
'PhutilJSONParserTestCase' => 'parser/__tests__/PhutilJSONParserTestCase.php',
@@ -720,6 +722,8 @@
'PhutilIrreducibleRuleParserGeneratorException' => 'PhutilParserGeneratorException',
'PhutilJIRAAuthAdapter' => 'PhutilOAuth1AuthAdapter',
'PhutilJSON' => 'Phobject',
+ 'PhutilJSONFragmentLexer' => 'PhutilLexer',
+ 'PhutilJSONFragmentLexerHighlighterTestCase' => 'PhutilTestCase',
'PhutilJSONParser' => 'Phobject',
'PhutilJSONParserException' => 'Exception',
'PhutilJSONParserTestCase' => 'PhutilTestCase',
diff --git a/src/lexer/PhutilJSONFragmentLexer.php b/src/lexer/PhutilJSONFragmentLexer.php
new file mode 100644
--- /dev/null
+++ b/src/lexer/PhutilJSONFragmentLexer.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * Syntax highlighting lexer for JSON fragments.
+ */
+final class PhutilJSONFragmentLexer extends PhutilLexer {
+
+ protected function getRawRules() {
+ return array(
+ 'start' => array(
+ array('"', 's', 'double-quoted-string'),
+ array('\s+', null),
+ array('[\\[\\]{},:]', 'o'),
+ array('(?:true|false|null)', 'k'),
+ array('-?\d+(\.\d+([eE][-+]?\d+)?)?', 'mf'),
+ array('.', null),
+ ),
+ 'double-quoted-string' => array(
+ array('[^"\\\\]+', 's'),
+ array('"', 's', '!pop'),
+ array('\\\\u[0-9a-fA-F]{4}', 'k'),
+ array('\\\\.', 'k'),
+ ),
+ );
+ }
+
+}
diff --git a/src/markup/syntax/engine/PhutilDefaultSyntaxHighlighterEngine.php b/src/markup/syntax/engine/PhutilDefaultSyntaxHighlighterEngine.php
--- a/src/markup/syntax/engine/PhutilDefaultSyntaxHighlighterEngine.php
+++ b/src/markup/syntax/engine/PhutilDefaultSyntaxHighlighterEngine.php
@@ -80,6 +80,12 @@
->getHighlightFuture($source);
}
+ if ($language == 'json') {
+ return id(new PhutilLexerSyntaxHighlighter())
+ ->setConfig('lexer', new PhutilJSONFragmentLexer())
+ ->getHighlightFuture($source);
+ }
+
if ($language == 'invisible') {
return id(new PhutilInvisibleSyntaxHighlighter())
->getHighlightFuture($source);
diff --git a/src/markup/syntax/highlighter/__tests__/PhutilJSONFragmentLexerHighlighterTestCase.php b/src/markup/syntax/highlighter/__tests__/PhutilJSONFragmentLexerHighlighterTestCase.php
new file mode 100644
--- /dev/null
+++ b/src/markup/syntax/highlighter/__tests__/PhutilJSONFragmentLexerHighlighterTestCase.php
@@ -0,0 +1,24 @@
+<?php
+
+final class PhutilJSONFragmentLexerHighlighterTestCase extends PhutilTestCase {
+
+ public function testLexer() {
+ $highlighter = id(new PhutilLexerSyntaxHighlighter())
+ ->setConfig('language', 'json')
+ ->setConfig('lexer', new PhutilJSONFragmentLexer());
+
+ $path = dirname(__FILE__).'/data/jsonfragment/';
+ foreach (Filesystem::listDirectory($path, $include_hidden = false) as $f) {
+ if (preg_match('/.test$/', $f)) {
+ $expect = preg_replace('/.test$/', '.expect', $f);
+ $source = Filesystem::readFile($path.'/'.$f);
+
+ $this->assertEqual(
+ Filesystem::readFile($path.'/'.$expect),
+ (string)$highlighter->getHighlightFuture($source)->resolve(),
+ $f);
+ }
+ }
+ }
+
+}
diff --git a/src/markup/syntax/highlighter/__tests__/data/jsonfragment/basics.expect b/src/markup/syntax/highlighter/__tests__/data/jsonfragment/basics.expect
new file mode 100644
--- /dev/null
+++ b/src/markup/syntax/highlighter/__tests__/data/jsonfragment/basics.expect
@@ -0,0 +1,12 @@
+<span class="o">{</span>
+ <span class="s">&quot;key&quot;</span><span class="o">:</span> <span class="mf">3.5</span><span class="o">,</span>
+ <span class="s">&quot;true&quot;</span><span class="o">:</span> <span class="k">true</span><span class="o">,</span>
+ <span class="s">&quot;false&quot;</span><span class="o">:</span> <span class="k">false</span><span class="o">,</span>
+ <span class="s">&quot;null&quot;</span><span class="o">:</span> <span class="k">null</span><span class="o">,</span>
+ <span class="s">&quot;list&quot;</span><span class="o">:</span> <span class="o">[</span><span class="mf">1</span><span class="o">,</span> <span class="mf">2</span><span class="o">,</span> <span class="mf">3</span><span class="o">],</span>
+ <span class="s">&quot;object&quot;</span><span class="o">:</span> <span class="o">{</span>
+ <span class="s">&quot;k1&quot;</span><span class="o">:</span> <span class="s">&quot;v1&quot;</span>
+ <span class="o">},</span>
+ <span class="s">&quot;numbers&quot;</span><span class="o">:</span> <span class="o">[</span><span class="mf">0</span>e<span class="mf">1</span><span class="o">,</span> <span class="mf">1</span>e<span class="mf">-1</span><span class="o">,</span> <span class="mf">-1</span>e<span class="mf">-1</span><span class="o">,</span> <span class="mf">-1</span>e+<span class="mf">1</span><span class="o">],</span>
+ <span class="s">&quot;</span><span class="k">\&quot;\u1234</span><span class="s">&#039;abc[]{}...&quot;</span>
+<span class="o">}</span>
diff --git a/src/markup/syntax/highlighter/__tests__/data/jsonfragment/basics.test b/src/markup/syntax/highlighter/__tests__/data/jsonfragment/basics.test
new file mode 100644
--- /dev/null
+++ b/src/markup/syntax/highlighter/__tests__/data/jsonfragment/basics.test
@@ -0,0 +1,12 @@
+{
+ "key": 3.5,
+ "true": true,
+ "false": false,
+ "null": null,
+ "list": [1, 2, 3],
+ "object": {
+ "k1": "v1"
+ },
+ "numbers": [0e1, 1e-1, -1e-1, -1e+1],
+ "\"\u1234'abc[]{}..."
+}

File Metadata

Mime Type
text/plain
Expires
Thu, Oct 24, 10:40 PM (1 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6742904
Default Alt Text
D14292.id34498.diff (7 KB)

Event Timeline